Go指针VS值的方法规则

Go指针VS值的方法规则

Go-方法接受者是指针或值类型

一. 指针和值区别

指针,在c或者cpp中比较常见,专门用来操作内存。但是在Go中也实现了指针,不过此指针非c或者cpp指针,Go中的指针只是保存了变量的地址,它不会参与指针运算,比如:p++或者p--等。那Go中实现的指针到底有什么作用呢?

  • 传递变量的地址:在函数调用时,如果需要修改函数外的变量,可以通过传递变量的地址来实现。这样函数内部就可以通过指针来访问变量,从而修改变量的值。
  • 动态分配内存:指针可以用来动态分配内存。通过调用内置函数new可以创建一个新的对象,并返回指向该对象的指针。这种方式可以在程序运行时动态地分配内存,并且可以避免在编译时就确定内存大小的限制。
  • 传递大型结构体:在函数调用时,如果需要传递一个大型结构体,可以通过传递结构体的指针来避免数据拷贝的开销。
  • 实现数据结构指针可以用来实现各种数据结构,例如链表、树、图等。指针可以将不同的数据结构链接在一起,从而形成更复杂的结构。

值,非指针类型,它可以是命名类型,也可以是struct类型或者其他自定义类型。比如:

type Person struct {
    name string
}
p Person // Person就是值类型,p就是值类型的对象
p *Person // *Person是指针类型,p就是指针类型的对象

为什么要介绍这两俩呢,因为它俩水比较深,今天主要是介绍在方法中的区别

二. 在方法中的应用

在Go中,可以将值作为方法接收者,也可以将指针作为方法接收者。对于值类型的方法接收者,可以被值对象和指针对象调用。对于指针类型的方法接收者,可以被指针对象调用。

当一个方法被定义时,可以指定一个接收者来定义该方法所属的类型。接收者可以是任何类型,包括值类型和指针类型。如果接收者是值类型,则该方法可以被值对象和指针对象调用;如果接收者是指针类型,则该方法只能被指针对象调用。

例如,下面是一个值类型的方法:

type Person struct {
    name string
}

func (p Person) SayHello() {
    fmt.Println("Hello, my name is", p.name)
}

在上面的代码中,SayHello是一个值类型的方法,它的接收者是一个Person类型的值。这个方法可以被Person类型的值对象和指针对象调用:

// 值对象调用方法
person1 := Person{name: "abc"}
person1.SayHello()

// 指针对象调用方法
person2 := &Person{name: "def"}
person2.SayHello()

如果将接收者改为指针类型,则该方法只能被指针对象调用:

type Person struct {
    name string
}

func (p *Person) SayHello() {
    fmt.Println("Hello, my name is", p.name)
}

在上面的代码中,SayHello是一个指针类型的方法,它的接收者是一个Person类型的指针。这个方法只能被Person类型的指针对象调用:

// 指针对象调用方法
person := &Person{name: "abc"}
person.SayHello()

person1 := Person{name: "def"}
person1.SayHello()

不过有个例外:若该值是可寻址的,那么Go就会自动插入取址操作符来对付一般的通过值调用的指针方法。在我们的例子中,变量person1是可寻址的,因此我们只需通过person1.SayHello来调用它的SayHello方法,编译器会将它重写为(&persion1).SayHello)()。

三.为什么方法调用有这个规则呢

之所以会有这条规则是因为指针方法可以修改接收者;通过值调用它们会导致方法接收到该值的副本, 因此任何修改都将被丢弃,所以Go不允许这种错误。

取舍

  • 如果方法需要修改接受者本身,那无疑需要传指针副本,也就是使用指针方法
  • 当值比较大的时候,值拷贝代价会变大,这时候也该考虑使用指针方法
  • 不可变对象等右值不能使用指针方法,即左值是可以使用指针方法的

Go中左值和右值Go指针VS值的方法规则

关于Go编译器自动解引用

  • 用指针类型的实参调用形参为值类型的方法(会进行“自动解引用”,(*person2).SayHello())
  • 用值类型的实参调用形参为指针类型的方法(会进行“自动取引用”,(&person1).SayHello())

四. 小结

总之,Go中值类型的方法可以被值对象和指针对象调用,而指针类型的方法只能被指针对象调用。这种设计可以让程序员在编写代码时更加灵活,可以根据具体的场景选择合适的方法接收者。



  1.  高并发设计系列-数据库篇

  2. 高并发设计系列-缓存篇

  3. 高并发设计系列-消息队列篇

  4. 高并发设计系列-分布式篇

  5. 高并发设计系列-维护篇

  6. Nginx: 挂了怎么办?热部署了解吗?什么是鲸群效应?Nginx你不知道的那些事一

  7. Nginx:为什么高性能?Master&worker如何配合?负载均衡算法有哪些?七层和四层负载均衡了解吗?

  8. Nginx:epoll红黑树和双向链表究竟如何做到少量拷贝和轮循实现高并发的

  9. 从Reactor模式俯瞰Nginx,你会发现你与高手的差距就在设计模式上,不在内卷上

  10. Redis:6.0多线程无锁(lock-free)设计和多线程Reactor模式助力Redis QPS更上一层楼

  11. Bio多线程消费者模式撑起Redis后台任务的半壁江上,这篇我干了,大家随意!

  12. redis小白基础汇总

  13. Redis与MySQL双写一致性如何保证:延迟双删?binlog异步删除?

  14. 就因为他了解Reactor模式,他的同事们都被裁员了

  15. MySQL面试精选:MySQL并发复制与两次写,不知道了吧

  16. MySQL面试精选:MVCC你还不懂就看这篇,不懂你来找我

  17. MySQL精选面试:为什么需要B+树?其他结构不行吗

  18. MySQL面试精选:阿里双十一高并发扣减库存就一行SQL语句搞定,Nice!!!

  19. MySQL面试精选:emoji表情存储不进去?

原文始发于微信公众号(堆栈future):Go指针VS值的方法规则

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/159565.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!