在Go中什么时候使用指针?

简介: 在Go中什么时候使用指针?

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是mapfunc或者chan,不要使用指针
  • 如果receiver是slice并且该函数并不会修改此slice,不要使用指针
  • 如果该函数会修改receiver,此时一定要用指针
  • 如果receiver是struct并且包含互斥类型sync.Mutex,或者是类似的同步变量,receiver必须是指针,这样可以避免对象拷贝
  • 如果receiver是较大的struct或者array,使用指针则更加高效。多大才算大?假设struct内所有成员都要作为函数变量传进去,如果觉得这时数据太多,就是struct太大
  • 如果receiver是structarray或者slice,并且其中某个element指向了某个可变量,则这个时候receiver选指针会使代码的意图更加明显
  • 如果receiver使较小的struct或者array,并且其变量都是些不变量、常量,例如time.Time,value receiver更加适合,因为value receiver可以减少需要回收的垃圾量。
  • 最后,如果不确定用哪个,使用指针类的receiver

参考文章:

https://zhuanlan.zhihu.com/p/395747448

相关文章
|
2月前
|
存储 Go
Go to Learn Go之指针
Go to Learn Go之指针
27 0
|
2月前
|
存储 Go
Go: struct 结构体类型和指针【学习笔记记录】
本文是Go语言中struct结构体类型和指针的学习笔记,包括结构体的定义、成员访问、使用匿名字段,以及指针变量的声明使用、指针数组定义使用和函数传参修改值的方法。
|
3月前
|
存储 安全 Java
Go 指针
该文章深入探讨了Go语言中的指针概念,包括指针的获取、使用、限制以及如何安全地返回局部变量的地址,同时讨论了`unsafe.Pointer`在打破指针限制方面的作用。
16 3
|
3月前
|
存储 安全 Go
Go 中的指针:了解内存引用
Go 中的指针:了解内存引用
|
3月前
|
存储 安全 Go
深入理解 Go 语言中的指针类型
【8月更文挑战第31天】
42 0
|
3月前
|
存储 Go 开发者
掌握Go语言中的指针
【8月更文挑战第31天】
20 0
|
3月前
|
Go 计算机视觉
Go从入门到放弃之指针
Go从入门到放弃之指针
|
4月前
|
存储 Go
go切片和指针切片
go切片和指针切片
25 2
|
3月前
|
人工智能 Go
go切片参数传递用值还是指针
go切片参数传递用值还是指针
35 0
|
3月前
|
存储 人工智能 Java
深入理解 go reflect - 要不要传指针
深入理解 go reflect - 要不要传指针
19 0