Go -- 接口赋值
在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 -- 接口赋值的更多相关文章
- 【Go语言】面向对象扩展——接口
简单地说 Interface是一组Method的组合,可以通过Interface来定义对象的一组行为.如果某个对象实现了某个接口的所有方法,就表示它实现了该借口,无需显式地在该类型上添加接口说明. I ...
- 深入学习golang(5)—接口
接口 概述 如果说goroutine和channel是Go并发的两大基石,那么接口是Go语言编程中数据类型的关键.在Go语言的实际编程中,几乎所有的数据结构都围绕接口展开,接口是Go语言中所有数据结构 ...
- TypeScript学习指南第二章--接口(Interface)
接口(Interface) TypeScript的核心机制之一在于它的类型检查系统(type-checker)只关注一个变量的"模型(shape)" 稍后我们去了解这个所谓的形状是 ...
- Delphi 的接口机制——接口操作的编译器实现过程(2)
接口对象的内存空间 假设我们定义了如下两个接口 IIntfA 和 IIntfB,其中 ProcA 和 ProcB 将实现为静态方法,而 VirtA 和 VirtB 将以虚方法实现: IIntfA = ...
- Delphi 的接口机制——接口操作的编译器实现过程(1)
学习COM编程技术也快有半个月了,这期间看了很多资料和别人的程序源码,也尝试了用delphi.C++.C#编写COM程序,个人感觉Delphi是最好上手的.C++的模版生成的代码太过复杂繁琐,大量使用 ...
- Java基础学习(四)-- 接口、集合框架、Collection、泛型详解
接口 一.接口的基本概念 关键字为:Interface,在JAVA编程语言中是一个抽象类型,是抽象方法的集合.也是使用.java文件编写. 二.接口声明 命名规范:与类名的命名规范相同,通常情况下 ...
- Go第七篇之规范的接口
接口本身是调用方和实现方均需要遵守的一种协议,大家按照统一的方法命名参数类型和数量来协调逻辑处理的过程. Go 语言中使用组合实现对象特性的描述.对象的内部使用结构体内嵌组合对象应该具有的特性,对外通 ...
- [golang note] 接口使用
侵入式接口 √ 在其他一些编程语言中,接口主要是作为不同组件之间的契约存在,即规定双方交互的规约. √ 对契约的实现是强制的,即必须确保用户的确实现了该接口,而实现一个接口,需要从该接口继承. √ 如 ...
- Go语言 6 结构体、方法和接口
文章由作者马志国在博客园的原创,若转载请于明显处标记出处:http://www.cnblogs.com/mazg/ Go学习群:415660935 结构体(struct)是由一系列具有相同类型或不同类 ...
随机推荐
- custom post types 404 Page Error
问题: 注册新的文章类型后,用新的类型写文章,打开后报 404 错误 原因: 因为虽然注册了新的帖子类型,但WordPress还不知道如何处理它 解决: 到设置 -> 固定链接,重新点击保存,再 ...
- 使用python在校内发人人网状态(人人网看状态)_python
#_*_coding:utf_8_ from sgmllib import SGMLParserimport sys, urllib2, urllib, cookielibimport datetim ...
- Linux Shell系列教程之(二)第一个Shell脚本
本文是Linux Shell系列教程的第(二)篇,更多shell教程请看:Linux Shell系列教程 通过上一篇教程的学习,相信大家已经能够对shell建立起一个大体的印象了,接下来,我们通过一个 ...
- 使用runtime关联对象将视图添加到视图的类目里
//get方法 - (RJCircularLoaderView*)rj_circularLoaderView { RJCircularLoaderView *loaderView = objc_get ...
- [luoguP1640] [SCOI2010]连续攻击游戏(二分图最大匹配)
传送门 我们将每一个属性和物品连边,然后枚举从小到大属性跑匈牙利,直到找不到连边 #include <cstdio> #include <cstring> #include & ...
- poj1734Sightseeing trip
Sightseeing trip Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6811 Accepted: 2602 ...
- iOS-Core Data基础
Core Data基础 Core Data是一个API集合,被设计用来简化数据对象的持久存储. 在此先不普及概念,先通过一个简单的案例使用来感受一下Core Data的精妙之处. 在创建工程的时候勾选 ...
- 富文本编辑器quill---vue组件(vue-quill-editor)的使用
1.配置webpack plugin 解决以下报错 Uncaught TypeError: Cannot read property 'imports' of undefined (image-res ...
- Lua local function与function区别
1 使用function声明的函数为全局函数,在被引用时可以不会因为声明的顺序而找不到 2 使用local function声明的函数为局部函数,在引用的时候必须要在声明的函数后面 例子: 下面这段代 ...
- docker的通俗理解
自己买了个服务器,前不久搭建好的一个网站,想要再搞一个站点,无奈只能修改端口后,再部署另外一个站点.繁琐的配置运行环境,迁移网站,是否让你感觉到很繁琐?服务器不想用了,想搬迁到另外一台服务器去部署,先 ...