今天在看golang的教程 中解释当我们使用golang创建http服务时的内部原理。
golang创建http服务代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package mainimport ( "fmt" "net/http" ) func sayHelloName (w http.ResponseWriter, r *http.Request) { r.ParseForm() fmt.Println(r.Form) fmt.Println("Path: " , r.URL.Path) fmt.Println("Scheme: " , r.URL.Scheme) fmt.Println(r.Form["url_long" ]) for k, v := range r.Form { fmt.Println("key:" , k) fmt.Println("value:" , v) } fmt.Fprintf(w, "Hello astaixe!" ) } func main () { http.HandleFunc("/" , sayHelloName) err := http.ListenAndServe(":9090" , nil ) if err != nil { log.Fatal("ListenAndServe: " , err) } }
文章中解释了Handler
接口,并表示我们所写的sayHelloName
方法之所以能被当成Handler
接口的实现是因为在包中定义了HandlerFunc
:
1 2 3 4 5 6 type HandlerFunc func (ResponseWriter, *Request) // ServeHTTP calls f (w, r) . func (f HandlerFunc) ServeHTTP (w ResponseWriter, r *Request) { f(w, r) }
看到这部分其实我是一脸蒙圈的,示例代码中HandleFunc
方法的具体定义和实现没有在文章中给出,也没有说如何使用HandlerFunc
把一个方法转换为Handler
接口的实现。
经过一段时间的研究http包,其实如果在文章中给出HandleFunc
方法和ServeMux.HandleFunc
方法的实现会比较容易理解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 func HandleFunc (pattern string , handler func (ResponseWriter, *Request) ) { DefaultServeMux.HandleFunc(pattern, handler) } func (mux *ServeMux) HandleFunc (pattern string , handler func (ResponseWriter, *Request) ) { if handler == nil { panic ("http: nil handler" ) } mux.Handle(pattern, HandlerFunc(handler)) }
以上代码可以看出HandleFunc
的第二个参数其实是一个方法,然后在代码中用HandlerFunc(handler)
将handler
参数类型转换为HandlerFunc
类型,而HandlerFunc
类型实现了Handler
接口,这样就可以让用户自定义一个方法的实现,实际在内部是一个接口。
以下是我找到的一个定义函数类型的列子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 package main import ( "fmt" ) type adder interface { add(string ) int } type handler func (name string ) int //实现函数类型方法 func (h handler) add (name string ) int { return h(name) + 10 } func process (a adder) { fmt.Println("process:" , a.add("taozs" )) } func doubler (name string ) int { return len (name) * 2 } type myint int func (i myint) add (name string ) int { return len (name) + int (i) } func main () { var my handler = func (name string ) int { return len (name) } fmt.Println(my("taozs" )) fmt.Println(my.add("taozs" )) fmt.Println(handler(doubler).add("taozs" )) process(my) process(handler(doubler)) process(myint(8 )) }