這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
由於剛剛接觸golang,對語言和用法都不太熟,看到這種寫法感覺很奇怪:
type Handler interface { ServeHTTP(ResponseWriter, *Request)}type HandlerFunc func(ResponseWriter, *Request)func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r)}
我內心就覺得為啥要這麼多此一舉呢?把一個func
定義為一個類型,然後實現ServeHTTP
函數。為啥不直接用那個函數呢?
來看看http.ListenAndServe()介面的原型就明白了:
func ListenAndServe(addr string, handler Handler) error
函數的第二個參數是一個Handler interface
,也就是說要使用這個函數那麼需要傳入一個實現了ServerHTTP
函數的類型。
對於複雜的應用來說可能會專門定義一個struct
來實現http.Handler
介面,那麼就傳入這個struct
的案例進去就行了。但是如果簡單的應用也這麼做就有點划不來了,因此http
包提供了HandlerFunc
類型來輔助使用者將一個函數快速轉換為符合http.Handler
介面的類型。這種方法叫adapter function type
[1]
。
這種技巧的關鍵就是將符合介面的函數定義為類型,然後對這個類型實現介面中的函數,實現的時候就直接調用自身。使用的時候只需要將自訂的函數(原型相同)做類型轉換就完成了。
實際上不光是標準庫用到這樣的技巧,在很多golang
初學者都會看的groupcache
中也用到了[2]
。
參考
[1] https://github.com/gopherchina/conference/blob/master/2017/1.3%20Go%20coding%20in%20go%20way.pdf
[2] https://github.com/golang/groupcache/blob/master/groupcache.go