@[TOC](go type func() 自定義函數類型)
因看不懂 go 中的自定義函數類型,看了https://www.jianshu.com/p/431abe0d2ed5 理解了不少,特此搬運到自己博客
在看golang 的http服務部分代碼時,被golang 中的 type func()寫法難住了,一時沒看懂代碼。后來查資料后,有了一點理解。
在golang中可以通過這樣簡單實現一個http服務
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()
是一個注冊函數,傳一個string類型的路由,和一個函數,函數的參數為(http.ResponseWriter, *http.Request)。跟蹤進入函數,在golang 源碼net/http/server.go文件中
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
在HandleFunc調用了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))
}
在mux.Handle(pattern, HandlerFunc(handler)) 的第二個參數HandlerFunc(handler)是什么鬼。
跟進看一下
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
原來HandlerFunc 是用 type 定義的函數,而函數的類型就是最開始傳入的類型
func(ResponseWriter, *Request)
ServeHTTP是HandlerFunc的一個方法(注意一下,golang中方法和函數不是一回事)。並且HandlerFunc實現了 Handler接口
Handler接口定義:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
回到HandleFunc方法中,mux.Handle(pattern, HandlerFunc(handler))
的第二個參數是把傳入的函數 handler 強轉成 HandlerFunc類型,這樣handler就實現了Handler接口。
到這我們明白HandlerFunc(handler)
是把普通函數強轉成type定義的函數。
現在寫一個簡單的demo驗證一下:
package main
import "fmt"
func main() {
one(2,callback)
}
//需要傳遞函數
func callback(i int) {
fmt.Println("i am callBack")
fmt.Println(i)
}
//main 中調用的函數
func one(i int,f func(int)) {
two(i,fun(f))
}
//one() 中調用的函數
func two(i int, c Call) {
c.call(i)
}
//定義的type函數
type fun func(int)
//fun實現的Call接口的call()函數
func (f fun) call(i int) {
f(i)
}
//接口
type Call interface {
call(int)
}
先看一下程序的運行結果:
我們在main()函數中調用了one()函數,並傳入了callback()函數,最終調用了我們傳入的callback()函數。
理一下思路:
使用type定義函數 func(int)
定義 Call 接口,Call中有一個函數 call(int)
在main()中調用one(2, callback),在one()中調用two(),傳入two()函數前,對callback函數實現了類型轉換,從普通函數轉換成type定義的函數。
在 two() 中調用傳入的 c 因為 c 實現了 Call 接口,所以可以調用 call() 函數,最終調用了我們傳入的 callback() 函數。