【Go夯实基础】interface中不同接收者(值、指针)如何影响接口实例化过程

192 阅读1分钟

1、interface执行函数一个关键步骤

* 1func(t T) A(args){}---->func A(t T,args){}
* 2func(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
  • 上面的写法对应的数据结构是

4.png

  • 当将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
  • 上面的写法对应的数据结构是

5.png

  • 通过值传递来传递指针
    • 通过i.data指针获取内容(此时内容为指向类型T的指针)
    • 通过指针调用类型T的A和B方法。