go语言学习-接口赋值

kuoshuang · · 6804 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

在go语言中,接口赋值分为2中情况:

1、将对象实例赋值给接口;

2、将一个接口赋值给另一个接口。

 

1、将对象实例赋值给接口:

       要求对象实现了接口的所有方法。

 

2、将接口赋值给另一个接口:

       假设接口A中定义的所有方法,都在接口B中有定义,那么B接口的实例可以赋值给A的对象。反之不成立,除非A和B定义的方法完全一样(顺序不要求),这时A和B等价,可以相互赋值。

 

3、类实例化时指针或者实例区别:

       实例化类的时候,一般有2个方法:

(1) 用new(structName):这个方法得到的是*structName类型,即类的指针类型;

(2) 用structName{init para}:这个方法得到的是structName类型,即类的实例类型,不是指针。

 

 

注意:

类在实现接口的时候,要注意定义的时候,一般用类的指针传入,就可以了。因为如果用类的结构体的话,可能会导致“类没有实现接口中某个方法”的错误。详细举例:

 

packagemain

import"fmt"

 

typetmpInterfaceinterface{

    tmpFunc()

    tmpFuncPtr()

}

 

typetmpStructstruct{

 

}

 

func(ttmpStruct)tmpFunc(){

    fmt.Println("functmpFunc")

}

 

func(t*tmpStruct)tmpFuncPtr(){

    fmt.Println("functmpFuncPtr")

}

 

funcmain(){

    /*这里如果用new,则得到的是tmpStruct的指针,tmpInterface的2个方法都可用*/

    vart_ttmpInterface=new(tmpStruct)

    t_t.tmpFunc()

    t_t.tmpFuncPtr()

 

    /*这里如果用tmpStruct{},则得到的是tmpStruct的实例,tmpInterface的2个方法都可用*/

/*

    vart_ptrtmpInterface=tmpStruct{}

    t_ptr.tmpFunc()

    t_ptr.tmpFuncPtr()

*/

}

 

上面的main()函数中,如果用tmpStruct{}初始化(可以理解为构造函数,没有入参),得到的是 tmpStruct的类型,会编译出错:

cannot use tmpStruct literal(type tmpStruct) as type tmpInterface in assignment:tmpStruct does not implementtmpInterface(tmpFuncPtr method has pointer receiver)

 

个人理解:

    受之前对C++或者JAVA等面向对象语言的影响,我们会把定义类的代码(以及其方法)视为一体的,下面把代码再复制一份下来:

typetmpStructstruct{

 

}

func(ttmpStruct)tmpFunc(){

    fmt.Println("functmpFunc")

}

func(t*tmpStruct)tmpFuncPtr(){

    fmt.Println("functmpFuncPtr")

}

 

        如果把上面这些代码理解成C++中对类tmpStruct的定义,函数tmpFunc和tmpFuncPtr是类的2个成员函数,那么会难以理解为什么又会提示tmpStruct没有实现tmpFuncPtr这个方法的提示。

    其实go语言中,interface和struct之间的关系和传统的面向对象中的是非常不一样的,接口和类之间耦合度非常低。同时,对其之间关系起到连接作用的“成员函数”,个人感觉和类以及接口的耦合度也是非常低的,倒不如直接把这些“成员函数”直接理解成普通的方法,只是go语言中允许这样的特殊语法形式定义:

关键字        传入的类/类指针     正常的函数定义

func           (t tmpStruct)      tmpFunc() {…}

func           (t *tmpStruct)     tmpFuncPtr(){…}

 

        在用类的实例/实例指针初始化接口的对象时:

vart_ttmpInterface=new(tmpStruct)

由于new返回的是一个指针,所以这里相当于t_t是一个*tmpStruct类型的变量,所以在调用函数的时候,给函数传入的就是一个指针。

    摘抄一句《Go语言编程》里面的话(3.5.3:接口赋值):

           Go语言可以根据下面的函数:

func (a Integer) Less(b Integer) bool

自动生成一个新的Less()方法:

func (a *Integer) Less(b Integer) bool {…}

    就是说,有了结构体类型作为入参的函数,go语言会自动创建一个相应的指针作为入参的函数,但是只有指针入参的函数,不会创建相应的结构体类型的函数。

   

    如果这样定义:

vart_ptrtmpInterface=tmpStruct{}

    tmpStruct{}的结果是tmpStruct类型,如果允许赋值给t_ptr成功的话,那么调用t_ptr.tmpFuncPtr时因为传入类型错误,所以这个角度看,go直接让编译不通过也是可以理解的。

 

 

 

总结:如果类的“成员函数”中有传入结构体指针类型的,则必须用结构体指针类型实例化接口的实例。

 


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:kuoshuang

查看原文:go语言学习-接口赋值

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

6804 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传