package main import "fmt" type t struct { s string } func (o t) f1() { o.s = "f1" } func (p *t) f2() { p.s = "f2" } func main() { t1 := t{ s: "t1",} fmt.Println("t1:",t1.s) t1.f1() fmt.Println("t1:",t1.s) t2 := t{ s: "t2",} fmt.Println("t2:",t2.s) t2.f2() fmt.Println("t2:",t2.s) } // t1: t1 // t1: t1 // t2: t2 // t2: f2
http://golang.org/doc/faq#methods_on_values_or_pointers (官方FAQ)
Should I define methods on values or pointers?
func (s *MyStruct) pointerMethod() { } // method on pointer func (s MyStruct) valueMethod() { } // method on value
For programmers unaccustomedto pointers,the distinctionbetween these two examples can be confusing,but the situationis actually very simple. When defininga method on a type,the receiver(s
in the above examples) behavesexactly as if it were an argumentto the method. Whether to define the receiver as a value or as a pointer is the same question,then,as whether a function argument should be a value or a pointer. There are several considerations.
First,and most important,does the method need to modify the receiver? If it does,the receivermustbe a pointer. (Slices and mapsact as references,so their story is a little more subtle,but for instance to change the length of a slicein a method the receiver must still be a pointer.) In the examplesabove,ifpointerMethod
modifies the fields ofs
,the caller will see those changes,butvalueMethod
is called with a copy of the caller's argument (that's the definition of passing a value),so changes it makes will be invisible to the caller.
By the way,pointer receivers are identicalto the situationin Java,although in Java the pointers are hidden under the covers; it's Go's value receivers that are unusual.
Second is the considerationof efficiency. If the receiver is large,a bigstruct
for instance,it will be much cheaperto use a pointer receiver.
Next is consistency. If some of the methods of the type must have pointer receivers,the rest should too,so the method set is consistentregardless of how the type is used. See the section onmethod setsfor details.
For types such as basic types,slices,and smallstructs
,a value receiver is very cheap so unless the semantics of the method requires a pointer,a value receiver is efficient and clear.