由于刚刚接触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
网友评论