本文来源于: https://gobea.cn/blog/detail/15zqpwrq.html
最简单的http服务
对于golang
来说,创建一个http服务是轻而易举的事情,如下,我们创建了一个非常简单的http服务,监听8899端口,只提供一个接口返回hello world
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello world")
})
http.ListenAndServe(":8899", nil)
}
当你在游览器输入http://127.0.0.1:8899
时,便能看到hello world
的输出
http服务
对于golang
的http服务,我们主要理解两个对象,:
Handler
,它是请求的处理对象,Handler
对象需要实现ServeHTTP
方法,ServeHTTP
执行的是我们的业务逻辑,一般我们定义的func(w http.ResponseWriter, r *http.Request)
的方法需要经过http.HandlerFunc
包装为Handler
对象ServeMux
,它相当于一个路由注册器,保存的请求路径pattern
和Handler
对象的map表,通过pattern
找到对应的Handler
对象,然后执行Handler
对象的ServeHTTP
方法
简单的说,http的执行对象是handler
,而要成为handler
对象.则必须实现ServeHTTP
方法,例如HandlerFunc
实现了ServeHTTP
方法,所以它也是一个handler
对象
handler对象
// Handler接口
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
// HandlerFunc实现了Handler接口
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
server从路由中找到handler
对象,执行handler
对象中的ServeHTTP
方法,也就是说,要作为路由的Handler
对象,需要实现ServeHTTP
方法,有关handler如下:
- handler函数,具有
func(w http.ResponseWriter, r *http.Requests)
签名的函数,需要经过HandlerFunc
函数包装,否则不能作为路由的Handler
对象, - handler处理函数,经过
HandlerFunc
结构包装的handler函数,HandlerFunc
实现了ServeHTTP
接口方法的函数 - handler对象,实现了Handler接口
ServeHTTP
方法的结构
注册路由ServeMux
type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
hosts bool
}
type muxEntry struct {
explicit bool
h Handler
pattern string
}
// ServeMux也拥有ServeHTTP方法,也就说ServeMux实现了Handler接口,即ServeMuX其实也是一个Handler对象,不过ServeMux的ServeHTTP方法不是用来处理request和respone,而是用来找到路由注册的handler
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
if r.RequestURI == "*" {
if r.ProtoAtLeast(1, 1) {
w.Header().Set("Connection", "close")
}
w.WriteHeader(StatusBadRequest)
return
}
h, _ := mux.Handler(r)
h.ServeHTTP(w, r)
}
如上,ServeMux.m
保存了路由规则pattern
以及对应的Handler
处理对象,另外ServeMux
也拥有ServeHTTP
方法,也就说ServeMux
实现了Handler
接口,即ServeMuX
其实也是一个Handler
对象,不过ServeMux的ServeHTTP方法不是用来处理request和respone,而是用来找到路由注册的handler
package main
import (
"fmt"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello world")
})
mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello world")
})
http.ListenAndServe(":8899", mux)
}
Server
http.ListenAndServe(":8899",mux)
// 等价于
serv := &http.Server{
Addr: ":8899",
Handler: mux,
}
serv.ListenAndServe()
http.ListenAndServe源码如下:
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。