1.1 最简单的方式
通过查看http.ListenAndServe的源码可以知道,其第一个参数是监听地址,第二个参数是一个Handler接口类型, 只要是实现了这个接口的ServeHTTP函数即可。这里的http.ListenAndServe函数会创建一个server结构体实例, 并将server的Handler属性赋值为我们手动实现的Handler接口。
1 | // 这里aa实现了http.Handler接口,便可以直接通过该接口返回 |
1 | //http.ListenAndServe函数说明 |
1.2 自定义server
1.1的方式调用http.ListenAndServe会默认创建一个server, 但是这样的server, 我们不能更好的控制server的其他参数,如超时等
server 启动过函数:
1 | type aa struct { |
这里可以再看看http.Server的定义:
1 | type Server struct { |
server 超时参数的跨度图:
1.3 更具花样的Handler
下面是一个我们常用等一种启动http server等方式,这里主要在实现Handler接口时,做了更多工作,主要是使用了一个多路选择器ServerMux去对不同等url pattern做不同的匹配处理,先看一个最常见的例子,这里未创建新的serveMux,会使用默认的DefaultServeMux:
1 | func h(res http.ResponseWriter, req *http.Request) { |
说明:
这里的http.HandleFunc的功能是向http包的DefaultServeMux加入新的处理路由。1
2
3func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
DefaultServeMux是一个ServeMux结构体的实例,其中有个m属性是一个map类型,存放了不同URL pattern的处理Handler。同时ServeMux也实现了ServeHTTP函数,是http.Handler接口的实现。 其类型定义如下:
1 | type ServeMux struct { |
1.4 使用自定义的serveMux
我们也可以不使用默认的serveMux,去自己初始化一个serveMux, 可以调用http.NewServeMux(),或者直接NewServeMux{}的方式去创建。下面的例子在构建server时,还是使用默认的server, 可以参考1.2节,创建自定义的server.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// test3 我们可以增加一个ServeMux来做一个请求路由处理工作
func h(res http.ResponseWriter, req *http.Request) {
res.Write([]byte("new pattern"))
}
func test3() {
mux := http.NewServeMux()
//通过HandleFunc函数去向mux中handler中注册处理函数
mux.HandleFunc("/test", func(res http.ResponseWriter, req *http.Request) {
res.Write([]byte("test3333"))
})
// 直接调用Handle函数去注册处理函数,
// 这里的http.HandleFunc 是一个type类型,这里调用将h转换为一个Handler接口的实现
mux.Handle("/st", http.HandlerFunc(h))
// 这里会使用默认创建的server
//也可以参考1.2创建自定义的server
http.ListenAndServe(":8082", mux)
}
1.6 go-restful中创建http server的方式
网上基于net/http包封装的http 框架有很多, 介绍一个我常用的库,go-restful,k8s的apiserver部分使用了这个库,算是一个比较优秀的rest库了。
在这个框架下,有如下几个基本概念
- container
- webservice
- route
一个container是用来包括一组webservice, 一个webservice包含多个route, 每个route代表了对一个URL pattern的处理, 这里看一个使用默认container的例子1
2
3
4
5
6
7
8
9
10
11 // 这里使用默认的container
ws := new(restful.WebService)
ws.Route(ws.GET("/default").To(h))
restful.Add(ws)
go func() {
http.ListenAndServe(":8080", nil)
}()
func h(req *restful.Request, resp *restful.Response) {
io.WriteString(resp, "default container")
}
下面再看一个使用自定义container的例子:1
2
3
4
5
6
7// container 同样实现了http.Hadler接口
c := restful.NewContainer()
ws2 := new(restful.WebService)
ws2.Route(ws2.GET("/hello").To(hello2))
c.Add(ws2)
server := &http.Server{Addr: ":8081", Handler: c}
log.Fatal(server.ListenAndServe())
这里可以展开看一下container的Add函数,主要就是执行的c.addHandler(service, c.ServeMux)函数,将container的dispatch函数加入到serverMux,作为URL pattern的handler。有兴趣的可以详细去看下
1 | func (c *Container) Add(service *WebService) *Container { |