1 在方法中使用指针
什么是receiver?
func (t T) method_name(t T){}
这里面的T就是receiver
- 使用receiver作为方法参数
func main() { r := receiver{Name: "zs"} fmt.Println(r) r.methodA() fmt.Println(r) } type receiver struct { Id int Name string Age int } func (receiver receiver) methodA() { receiver.Name = "ls" } func (receiver *receiver) methodB() { receiver.Name = "ls" }
结果:
{0 zs 0}
{0 zs 0}
- 使用*receiver作为方法参数
func main() { r := receiver{Name: "zs"} fmt.Println(r) r.methodB() fmt.Println(r) } type receiver struct { Id int Name string Age int } func (receiver receiver) methodA() { receiver.Name = "ls" } func (receiver *receiver) methodB() { receiver.Name = "ls" }
结果:
{0 zs 0}
{0 ls 0}
2 在结构体中使用指针
- 方式一
func main() { student := Student{Map: map[string]int{"S": 0}, ReceiverA: receiver{Name: "A"}, ReceiverB: &receiver{Name: "B"}} fmt.Println(student, *student.ReceiverB) student.updateA() fmt.Println(student, *student.ReceiverB) } type receiver struct { Id int Name string Age int } type Student struct { No int Map map[string]int ReceiverA receiver ReceiverB *receiver } func (stu Student) updateA() { stu.Map["a"] = 1 stu.ReceiverA = receiver{Name: "ww"} stu.ReceiverB = &receiver{Name: "ww"} } func (stu *Student) updateB() { stu.Map["b"] = 2 stu.ReceiverA = receiver{Name: "ww"} stu.ReceiverB = &receiver{Name: "ww"} }
结果:
{0 map[S:0] {0 A 0} 0xc0000b4000} {0 B 0}
{0 map[S:0 a:1] {0 A 0} 0xc0000b4000} {0 B 0}
- 方式二
func main() { student := Student{Map: map[string]int{"S": 0}, ReceiverA: receiver{Name: "A"}, ReceiverB: &receiver{Name: "B"}} fmt.Println(student, *student.ReceiverB) student.updateA() fmt.Println(student, *student.ReceiverB) } type receiver struct { Id int Name string Age int } type Student struct { No int Map map[string]int ReceiverA receiver ReceiverB *receiver } func (stu Student) updateA() { stu.Map["a"] = 1 stu.ReceiverA = receiver{Name: "ww"} stu.ReceiverB = &receiver{Name: "ww"} } func (stu *Student) updateB() { stu.Map["b"] = 2 stu.ReceiverA = receiver{Name: "ww"} stu.ReceiverB = &receiver{Name: "ww"} }
结果:
{0 map[S:0] {0 A 0} 0xc0000b4000} {0 B 0}
{0 map[S:0 b:2] {0 ww 0} 0xc0000b4060} {0 ww 0}
3 什么时候使用指针
一个函数何时该用指针类型做receiver对初学者而言一直是个头疼的问题。下面是列举了一些常用的判断指导。
- 如果receiver是
map
、func
或者chan
,不要使用指针 - 如果receiver是
slice
并且该函数并不会修改此slice,不要使用指针 - 如果该函数会修改receiver,此时一定要用指针
- 如果receiver是
struct
并且包含互斥类型sync.Mutex
,或者是类似的同步变量,receiver必须是指针,这样可以避免对象拷贝 - 如果receiver是较大的
struct
或者array
,使用指针则更加高效。多大才算大?假设struct内所有成员都要作为函数变量传进去,如果觉得这时数据太多,就是struct太大 - 如果receiver是
struct
,array
或者slice
,并且其中某个element指向了某个可变量,则这个时候receiver选指针会使代码的意图更加明显 - 如果receiver使较小的
struct
或者array
,并且其变量都是些不变量、常量,例如time.Time
,value receiver更加适合,因为value receiver可以减少需要回收的垃圾量。 - 最后,如果不确定用哪个,使用指针类的receiver
参考文章: