go语言 指针类型的方法接受者和非指针类型的方法接受者之间的区别

近来写了一些go语言程序,对go语言的操作也没有觉得特别有问题,今天因为一个手误,将本来该写成指针的方法,写成了非指针,一直没有深入思考过这个问题。于是查了一些资料,做一个简单的记录。

本文主要记录了go语言 指针类型的方法接受者和非指针类型的方法接受者之间的区别,以及这两种写法自己的理解。

go语言 指针类型的方法接受者和非指针类型的方法接受者之间的区别

先看一个非常常见的例子,很多讲解 指针方法接受者和非指针类型的方法接受者之间区别的文章都举的例子。

指针类型的方法接受者:

  1. package main
  2. import "fmt"
  3. type Person struct {
  4. name string
  5. age int
  6. }
  7. func (v *Person) changeName(name string) {
  8. p := v
  9. p.name = name
  10. }
  11. func main() {
  12. xiaoMing := Person{name: "lilei", age: 33}
  13. xiaoMing.changeName("hanmeimei")
  14. fmt.Println(xiaoMing.name)
  15. }

输出结果为:
hanmeimei

以上写法没有问题,结果也是希望看到的。

非指针类型的方法接受者

  1. package main
  2. import "fmt"
  3. type Person struct {
  4. name string
  5. age int
  6. }
  7. //就这里把 * 好去掉了。
  8. func (v Person) changeName(name string) {
  9. p := v
  10. p.name = name
  11. }
  12. func main() {
  13. xiaoMing := Person{name: "lilei", age: 33}
  14. xiaoMing.changeName("hanmeimei")
  15. fmt.Println(xiaoMing.name)
  16. }

输出结果为:
lilei

从以上代码的运行结果可以得出如下结论:

  1. 1. 指针类型的方法接受者:能够改变原先结构体的数值
  2. 2. 非指针类型的方法接受者:不能够改变原来结构体的数值。

上面的说法个人的理解为:

在调用Persion的对象 xiaoMing 上的方法modifyName() 的时候,表面上我们仅仅传递了一个参数 “hanmeimei”。 其实传递了两个参数,一个隐藏的参数就是 xiaoMing本身。 有点类似C++ 中的this,或者说叫做上下文,或者调用者本身。

  1. 方法的接受者为指针
  2. func (v *Person) changeName(name string) {
  3. p := v
  4. p.name = name
  5. }
  6. //方法接受者不是指针的时候
  7. func (v Person) changeName(name string) {
  8. p := v
  9. p.name = name
  10. }

既然传递了两个参数一个是 参数列表中的 name 字段。另外一个就是 xiaoMing本身,将xiaoMing对象传递给 上面的 方法接受者 v 。

  1. 如果方法接受者是指针,则传递过去的时候,是同一个对象的引用,也就是将xiaoMing的指针赋值给了v v xiaoMing是同一个对象,所以在方法内部修改属性的值,属性的值是发生改变的
  2. 如果方法接受者不是指针,则传递过去的时候,是该对象xiaoMing的一个copy,在内部修改了对应的属性,和xiaoMing对象已经不是同一个对象了,因此在输出xiaoMing.name 的时候,该值并没有发生变化。
2021-08-12 23:21:15  user 阅读(108) 评论(0) 标签:go指针类型的方法接受者,非指针类型的方法接受者 分类:go语言