|
Go语言标准库内建net/http包,不仅提供了Http 发送POST、GET等请求的客户端方法,还提供了编写服务器处理的一些方法。下面简单介绍如何启动一个服务器,并注册处理程序。最后介绍gin框架中启动服务的原理。
HTTP Server
net/http包提供http.ListenAndServe()可以直接创建一个监听服务器。用来侦听TCP网络地址addr,然后使用处理程序调用来处理传入的请求。如果handler为nil,则使用默认的http.DefaultServeMux进行处理。
当调用http.Handle()或http.HandleFunc()时,默认注入http.DefaultServeMux中。http.DefaultServeMux是ServeMux结构体的实例。ServeMux是一个HTTP请求多路复用器。它将每个传入请求的URL与已注册模式列表进行匹配,并调用匹配模式的处理程序。
//注册处理程序需要实现Handler接口
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
//src/net/http/server.go
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
//在DefaultServeMux中注册处理程序
func Handle(pattern string, handler Handler) {
DefaultServeMux.Handle(pattern, handler)
}
//在DefaultServeMux中注册处理程序函数
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
示例代码:
type HttpHandler struct {
}
func (*HttpHandler) ServeHTTP(writer http.ResponseWriter, http *http.Request) {
fmt.Println(http.URL, http.Header)
writer.Write([]byte("hello"))
}
func main() {
log.Fatal(http.ListenAndServe(":8080", new(HttpHandler)))
}如果需要更多地控制服务端行为可以自定义http.Server。
server := http.Server{
Addr: "127.0.0.1:9001",
Handler: new(HttpHandler),
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
//http.Handle("/one", new(HttpHandler))
http.HandleFunc("/foo", func(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte("hello,I'm foo!"))
})
log.Fatal(server.ListenAndServe())下面写法也是很常见的,先使用net.Listen创建一个listener,然后调用http.Serve启动监听程序
func main() {
lis, err := net.Listen("TCP", "8080")
if err != nil {
fmt.Printf("listen addr fail,err:%v\n", err)
return
}
http.HandleFunc("/foo", func(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte("hello,I'm foo!"))
})
log.Fatal(http.Serve(lis, nil))
//或者这样也可以
//server := &http.Server{}
//server.Serve(lis)
}Gin框架Web处理器原理
在我们使用gin启动一个web服务,下面几行代码就能完成,是不是很简单。
func main() {
r := gin.Default()
//router.InitRouter(r)
err := r.Run(config.C.Server.Addr)
if err != nil {
log.Fatal(err)
}
}那么它是如何处理的呢?关键时看Engine.Run方法怎么运行的。
// 此处Engine实现了http.Handler 接口
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
c := engine.pool.Get().(*Context)
c.writermem.reset(w)
c.Request = req
c.reset()
engine.handleHTTPRequest(c)
engine.pool.Put(c)
}
//返回Engine指针对象
func (engine *Engine) Handler() http.Handler {
if !engine.UseH2C {
return engine
}
h2s := &http2.Server{}
return h2c.NewHandler(engine, h2s)
}
//启动服务
func (engine *Engine) Run(addr ...string) (err error) {
defer func() { debugPrintError(err) }()
if engine.isUnsafeTrustedProxies() {
debugPrint("[WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.\n" +
"Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.")
}
address := resolveAddress(addr)
debugPrint("Listening and serving HTTP on %s\n", address)
//看这里是不是调用的标准库的方法
err = http.ListenAndServe(address, engine.Handler())
return
} |
|