@@ -9,11 +9,11 @@ Go的http有两个核心功能:Conn、ServeMux
9
9
Go在等待客户端请求里面是这样写的:
10
10
``` Go
11
11
12
- c , err := srv.newConn (rw)
13
- if err != nil {
14
- continue
15
- }
16
- go c.serve ()
12
+ c , err := srv.newConn (rw)
13
+ if err != nil {
14
+ continue
15
+ }
16
+ go c.serve ()
17
17
18
18
```
19
19
这里我们可以看到客户端的每次请求都会创建一个Conn,这个Conn里面保存了该次请求的信息,然后再传递到对应的handler,该handler中便可以读取到相应的header信息,这样保证了每个请求的独立性。
@@ -24,85 +24,85 @@ Go在等待客户端请求里面是这样写的:
24
24
它的结构如下:
25
25
``` Go
26
26
27
- type ServeMux struct {
28
- mu sync.RWMutex // 锁,由于请求涉及到并发处理,因此这里需要一个锁机制
29
- m map [string ]muxEntry // 路由规则,一个string对应一个mux实体,这里的string就是注册的路由表达式
30
- hosts bool // 是否在任意的规则中带有host信息
31
- }
27
+ type ServeMux struct {
28
+ mu sync.RWMutex // 锁,由于请求涉及到并发处理,因此这里需要一个锁机制
29
+ m map [string ]muxEntry // 路由规则,一个string对应一个mux实体,这里的string就是注册的路由表达式
30
+ hosts bool // 是否在任意的规则中带有host信息
31
+ }
32
32
33
33
```
34
34
下面看一下muxEntry
35
35
``` Go
36
36
37
- type muxEntry struct {
38
- explicit bool // 是否精确匹配
39
- h Handler // 这个路由表达式对应哪个handler
40
- pattern string // 匹配字符串
41
- }
37
+ type muxEntry struct {
38
+ explicit bool // 是否精确匹配
39
+ h Handler // 这个路由表达式对应哪个handler
40
+ pattern string // 匹配字符串
41
+ }
42
42
43
43
```
44
44
接着看一下Handler的定义
45
45
``` Go
46
46
47
- type Handler interface {
48
- ServeHTTP (ResponseWriter, *Request) // 路由实现器
49
- }
47
+ type Handler interface {
48
+ ServeHTTP (ResponseWriter, *Request) // 路由实现器
49
+ }
50
50
51
51
```
52
52
Handler是一个接口,但是前一小节中的` sayhelloName ` 函数并没有实现ServeHTTP这个接口,为什么能添加呢?原来在http包里面还定义了一个类型` HandlerFunc ` ,我们定义的函数` sayhelloName ` 就是这个HandlerFunc调用之后的结果,这个类型默认就实现了ServeHTTP这个接口,即我们调用了HandlerFunc(f),强制类型转换f成为HandlerFunc类型,这样f就拥有了ServeHTTP方法。
53
53
``` Go
54
54
55
- type HandlerFunc func (ResponseWriter, *Request)
55
+ type HandlerFunc func (ResponseWriter, *Request)
56
56
57
- // ServeHTTP calls f(w, r).
58
- func (f HandlerFunc ) ServeHTTP (w ResponseWriter, r *Request) {
59
- f (w, r)
60
- }
57
+ // ServeHTTP calls f(w, r).
58
+ func (f HandlerFunc ) ServeHTTP (w ResponseWriter , r *Request ) {
59
+ f (w, r)
60
+ }
61
61
```
62
62
路由器里面存储好了相应的路由规则之后,那么具体的请求又是怎么分发的呢?请看下面的代码,默认的路由器实现了` ServeHTTP ` :
63
63
``` Go
64
64
65
- func (mux *ServeMux ) ServeHTTP (w ResponseWriter, r *Request) {
66
- if r.RequestURI == " *" {
67
- w.Header ().Set (" Connection" , " close" )
68
- w.WriteHeader (StatusBadRequest)
69
- return
70
- }
71
- h , _ := mux.Handler (r)
72
- h.ServeHTTP (w, r)
65
+ func (mux *ServeMux ) ServeHTTP (w ResponseWriter , r *Request ) {
66
+ if r.RequestURI == " *" {
67
+ w.Header ().Set (" Connection" , " close" )
68
+ w.WriteHeader (StatusBadRequest)
69
+ return
73
70
}
71
+ h , _ := mux.Handler (r)
72
+ h.ServeHTTP (w, r)
73
+ }
74
74
```
75
75
如上所示路由器接收到请求之后,如果是` * ` 那么关闭链接,不然调用` mux.Handler(r) ` 返回对应设置路由的处理Handler,然后执行` h.ServeHTTP(w, r) `
76
76
77
77
也就是调用对应路由的handler的ServerHTTP接口,那么mux.Handler(r)怎么处理的呢?
78
78
``` Go
79
79
80
- func (mux *ServeMux ) Handler (r *Request) (h Handler, pattern string) {
81
- if r.Method != " CONNECT" {
82
- if p := cleanPath (r.URL .Path ); p != r.URL .Path {
83
- _, pattern = mux.handler (r.Host , p)
84
- return RedirectHandler (p, StatusMovedPermanently), pattern
85
- }
86
- }
87
- return mux.handler (r.Host , r.URL .Path )
88
- }
89
-
90
- func (mux *ServeMux ) handler (host, path string) (h Handler, pattern string) {
91
- mux.mu .RLock ()
92
- defer mux.mu .RUnlock ()
93
-
94
- // Host-specific pattern takes precedence over generic ones
95
- if mux.hosts {
96
- h, pattern = mux.match (host + path)
97
- }
98
- if h == nil {
99
- h, pattern = mux.match (path)
80
+ func (mux *ServeMux ) Handler (r *Request ) (h Handler , pattern string ) {
81
+ if r.Method != " CONNECT" {
82
+ if p := cleanPath (r.URL .Path ); p != r.URL .Path {
83
+ _, pattern = mux.handler (r.Host , p)
84
+ return RedirectHandler (p, StatusMovedPermanently), pattern
100
85
}
101
- if h == nil {
102
- h, pattern = NotFoundHandler (), " "
103
- }
104
- return
86
+ }
87
+ return mux.handler (r.Host , r.URL .Path )
88
+ }
89
+
90
+ func (mux *ServeMux ) handler (host , path string ) (h Handler , pattern string ) {
91
+ mux.mu .RLock ()
92
+ defer mux.mu .RUnlock ()
93
+
94
+ // Host-specific pattern takes precedence over generic ones
95
+ if mux.hosts {
96
+ h, pattern = mux.match (host + path)
97
+ }
98
+ if h == nil {
99
+ h, pattern = mux.match (path)
105
100
}
101
+ if h == nil {
102
+ h, pattern = NotFoundHandler (), " "
103
+ }
104
+ return
105
+ }
106
106
```
107
107
原来他是根据用户请求的URL和路由器里面存储的map去匹配的,当匹配到之后返回存储的handler,调用这个handler的ServeHTTP接口就可以执行到相应的函数了。
108
108
@@ -111,33 +111,33 @@ Handler是一个接口,但是前一小节中的`sayhelloName`函数并没有
111
111
如下代码所示,我们自己实现了一个简易的路由器
112
112
``` Go
113
113
114
- package main
114
+ package main
115
115
116
- import (
117
- " fmt"
118
- " net/http"
119
- )
116
+ import (
117
+ " fmt"
118
+ " net/http"
119
+ )
120
120
121
- type MyMux struct {
122
- }
121
+ type MyMux struct {
122
+ }
123
123
124
- func (p *MyMux ) ServeHTTP (w http.ResponseWriter, r *http.Request) {
125
- if r.URL .Path == " /" {
126
- sayhelloName (w, r)
127
- return
128
- }
129
- http.NotFound (w, r)
124
+ func (p *MyMux ) ServeHTTP (w http .ResponseWriter , r *http .Request ) {
125
+ if r.URL .Path == " /" {
126
+ sayhelloName (w, r)
130
127
return
131
128
}
132
-
133
- func sayhelloName (w http .ResponseWriter , r *http .Request ) {
134
- fmt.Fprintf (w, " Hello myroute!" )
135
- }
136
-
137
- func main () {
138
- mux := &MyMux{}
139
- http.ListenAndServe (" :9090" , mux)
140
- }
129
+ http.NotFound (w, r)
130
+ return
131
+ }
132
+
133
+ func sayhelloName (w http .ResponseWriter , r *http .Request ) {
134
+ fmt.Fprintf (w, " Hello myroute!" )
135
+ }
136
+
137
+ func main () {
138
+ mux := &MyMux{}
139
+ http.ListenAndServe (" :9090" , mux)
140
+ }
141
141
```
142
142
## Go代码的执行流程
143
143
0 commit comments