深入理解Go语言中指针接收器与值接收器的区别

超级欧派课程 2024-03-30 03:10:43

这篇文章将探讨关于Go语言中指针接收器和值接收器之间的细微差别。我们将逐步介绍这些差别,并通过示例代码进行说明。

1. 什么是值接收器与指针接收器?

Go语言中,每个方法都与一个接收器绑定,接收器可以是值类型(值接收器)或者是指向值类型的指针(指针接收器)。

值接收器:它基于值类型的副本来调用方法;任何对接收器的修改都不会影响原始值。指针接收器:它使用原始值的指针来调用方法;对接收器的修改将反映在原始值上。

2. 值类型和指针类型的方法调用

首先,无论是值类型T还是指针类型*T(前提是可寻址),它们都可以调用具有值接收器和指针接收器的方法。这是最基本的原则。

例如,如果一个类型有一个值接收器的方法,那么它可以在该类型的值本身和指向该值的指针上进行调用。同样地,对于指针接收器的方法,它可以在指针和该指针所指向的值本身上进行调用。

示例代码如下:

上述示例代码可以正常运行,没有任何编译错误。

需要注意的是,即使变量m不是指针类型,调用m.Transform()​仍然会改变其Model​值。这是因为Go语言会自动取值的地址来调用指针接收器方法,所以这相当于使用(&m).Transform()​的另一种方式。

所以,我们可以得出两个要点:

Go语言会自动取值的地址来调用指针接收器方法。它会自动解引用指针来调用值接收器方法。

这个细节经常被人们误解,实际上我们可以只使用值来调用指针接收器方法,而不需要使用指针。

3. nil的细微差别

接下来,我们来讨论一下关于nil指针的细微差别。让我们稍微修改一下例子,看看哪个例子会因为nil而导致恐慌。

这两个例子都不会引发恐慌,实际上我们可以使用nil指针调用函数,前提是该方法不访问结构体的任何字段。

但是,我们之前讨论过"Go在调用值接收器方法时会自动解引用指针"。那么,如果我们使用nil指针调用值接收器方法会发生什么呢?会导致恐慌吗?

是的,尝试在nil指针上调用值接收器方法(例如var car *Car; car.Move()​)会导致恐慌,因为Go无法在运行时将nil解引用并将其作为值传递。

4. 不可寻址的问题

接下来,我们来解决第一个要点的问题:"Go会自动取值的地址来调用指针接收器"。如果该值是"不可寻址"的,会发生什么呢?

从函数返回的值或临时值(例如结构体字面量或映射中的值)通常无法被寻址,因此无法在其上调用指针接收器方法。

下面是一个示例:

在这个示例中,我们试图在一个结构体字面量上调用指针接收器方法SetName​,但是它会导致编译错误。这是因为结构体字面量是不可寻址的,无法获取其指针。

要解决这个问题,我们可以首先将结构体字面量分配给一个变量,然后使用该变量调用方法:

这样就可以成功调用指针接收器方法了。

总结:无论是值类型还是指针类型,都可以调用具有值接收器和指针接收器的方法。使用指针调用值接收器方法会自动解引用指针。使用nil指针调用指针接收器方法是安全的,前提是该方法不访问结构体的任何字段。无法在不可寻址的值上调用指针接收器方法,需要先将其分配给一个变量。更多

希望这些解释能够帮助你更好地理解Go语言中指针接收器和值接收器之间的细微差别。如果你想了解更多的 golang 知识,请关注我的《Golang实用技巧》专栏,它将为你揭秘生产环境最佳实践,带你探索高并发编程的实用教程。从分享实用的Golang小技巧到深入剖析实际应用场景,让你成为真正的Golang大师。无论你是初学者还是经验丰富的开发者,这里都有你所需要的灵感和知识。让我们一同探索Golang的无限可能!

0 阅读:0

超级欧派课程

简介:感谢大家的关注