在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类型,即类的实例类型,不是指针。

注意:

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

package main

import "fmt"

type tmpInterface interface{

tmpFunc()

tmpFuncPtr()

}

type tmpStruct struct{

}

func(t tmpStruct)tmpFunc(){

fmt.Println("functmpFunc")

}

func(t *tmpStruct)tmpFuncPtr(){

fmt.Println("functmpFuncPtr")

}

funcmain(){

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

var t_t tmpInterface=new(tmpStruct)

t_t.tmpFunc()

t_t.tmpFuncPtr()

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

/*

var t_ptr tmpInterface=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等面向对象语言的影响,我们会把定义类的代码(以及其方法)视为一体的,下面把代码再复制一份下来:

type tmpStruct struct{

}

func(t tmpStruct)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(){…}

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

var t_t tmpInterface=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语言会自动创建一个相应的指针作为入参的函数,但是只有指针入参的函数,不会创建相应的结构体类型的函数。

如果这样定义:

var t_ptr tmpInterface=tmpStruct{}

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

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

Go -- 接口赋值的更多相关文章

  1. 【Go语言】面向对象扩展——接口

    简单地说 Interface是一组Method的组合,可以通过Interface来定义对象的一组行为.如果某个对象实现了某个接口的所有方法,就表示它实现了该借口,无需显式地在该类型上添加接口说明. I ...

  2. 深入学习golang(5)—接口

    接口 概述 如果说goroutine和channel是Go并发的两大基石,那么接口是Go语言编程中数据类型的关键.在Go语言的实际编程中,几乎所有的数据结构都围绕接口展开,接口是Go语言中所有数据结构 ...

  3. TypeScript学习指南第二章--接口(Interface)

    接口(Interface) TypeScript的核心机制之一在于它的类型检查系统(type-checker)只关注一个变量的"模型(shape)" 稍后我们去了解这个所谓的形状是 ...

  4. Delphi 的接口机制——接口操作的编译器实现过程(2)

    接口对象的内存空间 假设我们定义了如下两个接口 IIntfA 和 IIntfB,其中 ProcA 和 ProcB 将实现为静态方法,而 VirtA 和 VirtB 将以虚方法实现: IIntfA =  ...

  5. Delphi 的接口机制——接口操作的编译器实现过程(1)

    学习COM编程技术也快有半个月了,这期间看了很多资料和别人的程序源码,也尝试了用delphi.C++.C#编写COM程序,个人感觉Delphi是最好上手的.C++的模版生成的代码太过复杂繁琐,大量使用 ...

  6. Java基础学习(四)-- 接口、集合框架、Collection、泛型详解

    接口 一.接口的基本概念 关键字为:Interface,在JAVA编程语言中是一个抽象类型,是抽象方法的集合.也是使用.java文件编写.   二.接口声明 命名规范:与类名的命名规范相同,通常情况下 ...

  7. Go第七篇之规范的接口

    接口本身是调用方和实现方均需要遵守的一种协议,大家按照统一的方法命名参数类型和数量来协调逻辑处理的过程. Go 语言中使用组合实现对象特性的描述.对象的内部使用结构体内嵌组合对象应该具有的特性,对外通 ...

  8. [golang note] 接口使用

    侵入式接口 √ 在其他一些编程语言中,接口主要是作为不同组件之间的契约存在,即规定双方交互的规约. √ 对契约的实现是强制的,即必须确保用户的确实现了该接口,而实现一个接口,需要从该接口继承. √ 如 ...

  9. Go语言 6 结构体、方法和接口

    文章由作者马志国在博客园的原创,若转载请于明显处标记出处:http://www.cnblogs.com/mazg/ Go学习群:415660935 结构体(struct)是由一系列具有相同类型或不同类 ...

随机推荐

  1. vmware esxi 6.0 开启嵌套虚拟化

    环境描述: 已通过vSphere Client创建一个名字为centos7的虚拟机,现在需要打开该虚拟机的嵌套虚拟化功能. 第一步: 开启ESXi Shell 开启vSphere的ssh远程登录服务或 ...

  2. loj2000 「SDOI2017」数字表格

    there #include <iostream> #include <cstring> #include <cstdio> using namespace std ...

  3. Leetcode2--->链表中对应位相加(进位)

    题目: 给定两个单链表,单链表中的数都是非负数.链表中的数字都是反向存储的,,每个节点都是个位数,将链表对应的位相加,返回最终的结果: 举例: Input: (2 -> 4 -> 3) + ...

  4. SCOI 2010 滑雪

    题目描述 a180285非常喜欢滑雪.他来到一座雪山,这里分布着 MM 条供滑行的轨道和 NN 个轨道之间的交点(同时也是景点),而且每个景点都有一编号 ii ( 1 \le i \le N1≤i≤N ...

  5. TensorFlow——交互式使用会话:InteractiveSession类

    目的是在交互式环境下(如jupyter),手动设定当前会话为默认会话,从而省去每次都要显示地说明sess的繁琐,如:Tensor.ecal(session=sess)或sess.Operation.r ...

  6. Welcome-to-Swift-07闭包(Closures)

    闭包是自包含的函数代码块,可以在代码中被传递和使用. Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的 lambdas 函数比较相似. 闭包可 ...

  7. HDU——1163Eddy's digital Roots(九余数定理+同余定理)

    Eddy's digital Roots Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Oth ...

  8. Codeforces Round #345 (Div. 2)——B. Beautiful Paintings(贪心求上升序列个数)

    B. Beautiful Paintings time limit per test 1 second memory limit per test 256 megabytes input standa ...

  9. xml文档绑定某个属性值到treeview算法

    原文发布时间为:2008-08-10 -- 来源于本人的百度文章 [由搬家工具导入] using System.Xml; protected void Button2_Click(object sen ...

  10. FileUtils删除文件的工具类

    前提是知道文件在哪个文件夹下面然后到文件夹下面删除文件,如果文件夹也需要传参数需要对下面方法进行改造. ( 需要借助于commons-io.jar和ResourceUtils.java  ) 1.De ...