在看golang 的http服務(wù)部分代碼時(shí),被golang 中的 type func()寫(xiě)法難住了,一時(shí)沒(méi)看懂代碼贝攒。后來(lái)查資料后,有了一點(diǎn)理解时甚。
在golang中可以通過(guò)這樣簡(jiǎn)單實(shí)現(xiàn)一個(gè)http服務(wù)
package main
import "net/http"
func mHttp() {
http.HandleFunc("/", h)
http.ListenAndServe("0.0.0.0:8888",nil)
}
func h(w http.ResponseWriter, r *http.Request) {
}
http.HandleFunc()
是一個(gè)注冊(cè)函數(shù)隘弊,傳一個(gè)string類(lèi)型的路由,和一個(gè)函數(shù)荒适,函數(shù)的參數(shù)為(http.ResponseWriter, *http.Request)梨熙。跟蹤進(jìn)入函數(shù),在golang 源碼net/http/server.go文件中
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
在HandleFunc調(diào)用了DefaultServeMux.HandleFunc(pattern, handler)
至于這些函數(shù)是干啥的先不做探討吻贿,這不是本文的重點(diǎn)串结。
再次跟進(jìn)函數(shù)
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
if handler == nil {
panic("http: nil handler")
}
mux.Handle(pattern, HandlerFunc(handler))
}
在mux.Handle(pattern, HandlerFunc(handler)) 的第二個(gè)參數(shù)HandlerFunc(handler)
是什么鬼。
跟進(jìn)看一下
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
原來(lái)HandlerFunc 是用 type 定義的函數(shù)舅列,而函數(shù)的類(lèi)型就是最開(kāi)始傳入的類(lèi)型func(ResponseWriter, *Request)
ServeHTTP是HandlerFunc的一個(gè)方法(注意一下肌割,golang中方法和函數(shù)不是一回事)。并且HandlerFunc實(shí)現(xiàn)了 Handler接口
Handler接口定義:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
回到HandleFunc方法中帐要,mux.Handle(pattern, HandlerFunc(handler))
的第二個(gè)參數(shù)是把傳入的函數(shù) handler 強(qiáng)轉(zhuǎn)成 HandlerFunc類(lèi)型把敞,這樣handler就實(shí)現(xiàn)了Handler接口。
到這我們明白HandlerFunc(handler)
是把普通函數(shù)強(qiáng)轉(zhuǎn)成type定義的函數(shù)榨惠。
現(xiàn)在寫(xiě)一個(gè)簡(jiǎn)單的demo驗(yàn)證一下:
package main
import "fmt"
func main() {
one(2, callback)
}
//需要傳遞函數(shù)
func callback(i int) {
fmt.Println("i am callBack")
fmt.Println(i)
}
//main中調(diào)用的函數(shù)
func one(i int, f func(int)) {
two(i, fun(f))
}
//one()中調(diào)用的函數(shù)
func two(i int, c Call) {
c.call(i)
}
//定義的type函數(shù)
type fun func(int)
//fun實(shí)現(xiàn)的Call接口的call()函數(shù)
func (f fun) call(i int) {
f(i)
}
//接口
type Call interface {
call(int)
}
先看一下程序的運(yùn)行結(jié)果:
我們?cè)?strong>main()函數(shù)中調(diào)用了one()函數(shù)奋早,并傳入了callback()函數(shù),最終調(diào)用了我們傳入的callback()函數(shù)赠橙。
理一下思路:
使用type定義函數(shù) func(int)
定義 Call 接口耽装,Call中有一個(gè)函數(shù) call(int)
在main()中調(diào)用one(2, callback),在one()中調(diào)用two()期揪,傳入two()函數(shù)前掉奄,對(duì)callback函數(shù)實(shí)現(xiàn)了類(lèi)型轉(zhuǎn)換,從普通函數(shù)轉(zhuǎn)換成type定義的函數(shù)凤薛。
在 two() 中調(diào)用傳入的 c 因?yàn)?c 實(shí)現(xiàn)了 Call 接口姓建,所以可以調(diào)用 call() 函數(shù)诞仓,最終調(diào)用了我們傳入的 callback() 函數(shù)。