GO网络编程包net/http
net/http包提供了HTTP客户端和服务器的实现。
hello world
通过http.HandleFunc()和http.ListenAndServe()两个函数就可以轻松创建一个简单的Go web服务器,示例代码如下:
package main
import (
"fmt"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello!")
}
func main() {
http.HandleFunc("/hello", hello)
http.ListenAndServe(":8080", nil)
}
其中*http.Request表示 HTTP 请求对象,该对象包含请求的所有信息,如 URL、首部、表单内容、请求的其他内容等。http.ResponseWriter是一个接口类型:
type ResponseWriter interface
{ Header() Header Write([]byte) (int, error) WriteHeader(statusCode int) }
用于向客户端发送响应,实现了ResponseWriter接口的类型显然也实现了io.Writer接口。所以在处理函数index中,可以调用fmt.Fprintln()向ResponseWriter写入响应信息。
Server结构体
Server结构体代表一个HTTP服务器。这个结构体包含了若干配置选项,可以用来自定义服务器的行为。
type Server struct {
Addr string // HTTP服务器监听的地址
Handler Handler // 处理所有HTTP请求的处理器,Handler:nil表明服务器使用默认的多路复用器DefaultServeMux
TLSConfig *tls.Config // 用于TLS握手的配置
ReadTimeout time.Duration // 读取客户端请求的时间限制
WriteTimeout time.Duration // 写入客户端响应的时间限制
IdleTimeout time.Duration // 连接空闲超时时间
MaxHeaderBytes int // 请求头部的最大字节数
...
}
对应的方法:
func (srv *Server) ListenAndServe() error
ListenAndServe:启动服务器监听并服务HTTP请求。这个方法会阻塞调用者,直到服务器停止或发生错误。
路由注册方案
- 事件处理器的Handler接口定义如下,只要实现了这个接口,就可以实现自己的handler处理器。
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
使用Handler接口进行路由注册,将URL路径与handler关联起来:
package main
import (
"fmt"
"net/http"
)
// MyHandler 结构体
type MyHandler struct{}
// ServeHTTP 方法,使得 MyHandler 实现了 http.Handler 接口
func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, you've hit the home page!")
}
func main() {
// 创建 MyHandler 的实例
handler := MyHandler{}
// 使用 http.Handle 注册 handler 到默认的 ServeMux
http.Handle("/", &handler)
// 启动服务器
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}
实现handler接口还可以使用适配器HandlerFunc,允许一个普通函数满足http.Handler接口。这样,你可以直接使用函数作为HTTP处理器,而不需要创建一个结构体并实现ServeHTTP方法。
其源码为:
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
可以这样使用HandlerFunc:
var myHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, world!"))
})
- 使用
http.HandleFunc函数,允许使用普通函数作为http.Handler。如果有一个函数签名为func(ResponseWriter, *Request),可以直接用这个函数作为handler,而不需要专门实现http.Handler接口。将一个URL模式和对应的HandlerFunc关联起来,并注册到默认的ServeMux。
package main
import (
"fmt"
"net/http"
)
func main() {
// 使用 http.HandleFunc 注册一个函数作为 handler 到默认的 ServeMux
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, you've hit the home page!")
})
// 启动服务器
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}
多路复用器
ServeMux:根据请求的URL地址找到对应的处理器,调用处理器对应的ServeHTTP()方法处理请求。
DefaultServeMux是net/http包的默认多路复用器,其实就是ServeMux的一个实例。
HandleFunc()处理器函数会在内部调用DefaultServeMux对象对应的方法,其内部实现:
// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
http.Handle()函数可以调用DefaultServeMux.Handle()方法来处理请求。
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
自定义多路复用器
虽然默认的多路复用器很好用,但仍然不推荐使用,因为它是一个全局变量,所有的代码都可以修改它。有些第三方库中可能与默认复用器产生冲突。所以推荐的做法是自定义。
package main
import (
"fmt"
"net/http"
)
func newservemux(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "NewServeMux")
}
func newservemuxhappy(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Newservemuxhappy")
}
func newservemuxbad(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "NewServeMuxbad")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", newservemux)
mux.HandleFunc("/happy", newservemuxhappy)
mux.HandleFunc("/bad", newservemuxbad)
s := &http.Server{
Addr: ":8080",
Handler: mux,
}
s.ListenAndServe()
}