go结构体的值方法与指针方法

碰到的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type myHandler struct{}
func (_ *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello,this is version 2"))
}
func main(){
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("nihao"))
})
mux.Handle("/user", myHandler{})
}

报错cannot use myHandler literal (type myHandler) as type http.Handler in argument to mux.Handle: myHandler does not implement http.Handler (ServeHTTP method has pointer receiver)

追一下mux.Handle方法

1
2
3
4
5
6
7
func (mux *ServeMux) Handle(pattern string, handler Handler) {
...
}
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}

mux.Handle方法只需要第二个参数实现ServeHTTP方法即可

奇怪,这里传入的myHandler{}不是实现了ServeHTTP方法吗?

通过查资料得知指针类型(*T)对象包含接受者为T的方法,反之则不包含

放到这里意思就是,myHandler{}的指针(&myHandler{})实现了ServeHTTP方法,而myHandler对象本身没有实现

1
2
3
4
5
6
7
8
9
第一种改法
func (_ *myHandler)....
=>
func(_ myHandler)
第二种改法
mux.Handle("/user",myHandler{})
=>
mux.Handle("/user",&myHandler{})

值方法与指针方法

1
2
3
func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct) valueMethod() { } // method on value

那么什么时候用值方法,什么时候用指针方法呢?主要考虑以下一些因素:

1.如果方法需要修改receiver,那么必须使用指针方法;
2.如果receiver是一个很大的结构体,考虑到效率,应该使用指针方法;
3.一致性。如果一些方法必须是指针receiver,那么其它方法也应该使用指针receiver;
4.对于一些基本类型、切片、或者小的结构体,使用value receiver效率会更高一些。

参考

http://www.cnblogs.com/hustcat/p/4004642.html

https://golang.org/doc/faq#methods_on_values_or_pointers