我们来看下面一个示例程序,最下面的测试函数,其中有三行是正确的,一行是错误的,你知道为什么那一行是错的么?
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,所以不能直接调用指针函数。
官方文档是这个
里面提到:
加粗的部分是我加的,意思是只有变量,间接指针(比如一个实例对象的变量直接调指针函数,实际是编译器先转了一遍指针)或切片的index操作,才称之为addressable。