1、interface执行函数一个关键步骤
* 1、func(t T) A(args){}---->func A(t T,args){}
* 2、func(t *T) A(args){}---->func A(t *T,args){}
* 这个t到底是指针还是值,取决于初始化的右边到底是值还是&变量
1、值初始化实例
type T struct {}
type Ter interface{
A()
B()
}
func(t T) A(){}
func(t *T) B(){}
var t T
var i Ter = t
- 上面的写法对应的数据结构是
-
当将t实现接口Ter时,其实是将T类型内存拷贝一份,然后i.data指向新生成复制品的内存地址。当调用i.A()方法时,经过以下3个步骤:
- i.data指针获取内容(此时的内容是图中的T1实例)
- 获取i.data.A内存。
- 调用i.data.A()方法。
-
当调用i.B()方法时,由于receiver的是*T.B()和T.A()是不一样的,调用经过也存在区别:
- i.data指针获取内容(此时的内容是图中的T1实例)
- 由于i.data变量获取的内容是实例,所以需要进行取地址操作。但Go内部实现禁止对该复制品进行取地址操作,所以无法调用i.B()方法。
-
所以代码进行编译时会报错:
T does not implement Ter (B method has pointer receiver)
-
另一个人角度理解
func(t T) A(){}通过go提供的机制,可以生成
func(t *T) A(){ (*t).A() }- 而,
func(t *T) B(){}不可以生成
func(t T) B() (&t).B**()** }
2、指针初始化实例
var t T
var i Ter = &t
- 上面的写法对应的数据结构是
- 通过值传递来传递指针
- 通过i.data指针获取内容(此时内容为指向类型T的指针)
- 通过指针调用类型T的A和B方法。