我们来看下面一个示例程序,最下面的测试函数,其中有三行是正确的,一行是错误的,你知道为什么那一行是错的么?
package js
import (
"fmt"
"testing"
)
type Tester struct{}
func (t Tester) Operation1() {
fmt.Println("first")
}
func (t *Tester) Operation2() {
fmt.Println("second")
}
func TestNewTester(t *testing.T) {
Tester{}.Operation1() //正确
Tester{}.Operation2() //错误
new(Tester).Operation2() //正确
new(Tester).Operation1() //正确
}
有这么几个现象:
1)定义在对象上的函数,比如这个:
func (t Tester) Operation1() {
fmt.Println("first")
}
是直接可以通过下面的方式调用的
Tester{}.Operation1() //正确
但是定义在指针上的函数,比如:
func (t *Tester) Operation2() {
fmt.Println("second")
}
是不可以使用下面的方式调用的
Tester{}.Operation2() //错误
但是如果用new(Tester)定义出来的指针则都可以调用
new(Tester).Operation2() //正确
new(Tester).Operation1() //正确
如果没有测试过,我也一直有这么一种错觉,就是直接初始化的对象不能调用函数,但从上面我们就可以看出,中间还是有很多细微的地方。
那这是为什么呢?
应该是Tester{}这种方式定义出来的对象因为没有正式的指针引用过,是和reflect库提到过的一种叫addressable的状态有关。这种应该是还没有addressable,所以不能直接调用指针函数。
官方文档是这个
里面提到:
For an operandxof typeT, the address operation&xgenerates a pointer of type*Ttox. The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement,xmay also be a (possibly parenthesized) composite literal. If the evaluation ofxwould cause a run-time panic, then the evaluation of&xdoes too.
加粗的部分是我加的,意思是只有变量,间接指针(比如一个实例对象的变量直接调指针函数,实际是编译器先转了一遍指针)或切片的index操作,才称之为addressable。
本文探讨了Go语言中对象函数调用的规则,特别是针对非指针接收者和指针接收者的函数。示例代码展示了直接通过结构体实例调用非指针方法是允许的,而调用指针方法则需要使用指针实例或`new()`函数。这涉及到Go语言的地址运算符和对象的addressable状态。官方文档指出,只有变量、间接指针或特定索引操作才是addressable,因此非指针实例无法直接调用指针方法。
1096

被折叠的 条评论
为什么被折叠?



