go语言之接口一
在Go语言中,一个类只需要实现了接口要求的所有函数,我们就说这个类实现了该接口
我们定义了一个File类,并实现有Read()、Write()、Seek()、Close()等方法。设
想我们有如下接口:
type IFile interface {
Read(buf []byte) (n int,err error)
Write(buf []byte) (n int,err error)
Seek(off int4,whence int)(pos int64,err error)
Close() error
}
type IReader interface {
Read(buf []byte) (n int, err error)
}
type IWriter interface {
Write(buf []byte) (n int, err error)
}
type ICloser interface {
Close() error
}
尽管File类并没有从这些接口继承,甚至可以不知道这些接口的存在,但是File类实现了
这些接口,可以进行赋值:
var file1 IFile = new(File)
var file2 IReader = new(File)
var file3 IWriter = new(File)
var file4 ICloser = new(File)
接口赋值:
Go语言中分为如下两种情况的接口赋值
1 将对象实例赋值给接口
2 将一个接口赋值给另一个接口
1 对象实例赋值给接口:
func (a Integer) Less(b Integer) bool{
return a < b
}
func (a *Integer) Add(b Integer){
*a+=b
}
type LessAdder interface{
Less(b Integer) bool
Add(b Integer)
}
赋值的方式如下:
func main(){
var a Integer = 1
var LA LessAdder = a
LA.Less(3)
}
运行报错:
cannot use a (type Integer) as type LessAdder in assignment:
Integer does not implement LessAdder (Add method has pointer receiver)
这个错误的原因是因为Add方法的类型是指针的形式,由类型指针接收的方法必须由对象指针表示和传入。正确的传递方法应该是var LA LessAdder =&a。这样Add方法就能够满足了。那Less方法传递的是非指针,这个时候是否会报错呢?答案是不会的。原因在于Go语言可以根据下面的函数
func (a Integer) Less(b Integer) bool{
return a < b
}
自动生成一个新的Less方法
func (a *Integer) Less(b Integer) bool{
return (*a) < b
}
类型*Integer就既存在Less()方法,也存在Add()方法,满足LessAdder接口。而
从另一方面来说,根据
func (a *Integer) Add(b Integer)
这个函数无法自动生成以下这个成员方法:
func (a Integer) Add(b Integer) {
(&a).Add(b)
}
因为(&a).Add()改变的只是函数参数a,对外部实际要操作的对象并无影响,这不符合用
户的预期。所以,Go语言不会自动为其生成该函数。因此,类型Integer只存在Less()方法,
缺少Add()方法,不满足LessAdder接口.
2 将一个接口赋值给另一个接口
来看一个示例,这是第一个接口:
package one
type ReadWriter interface {
Read(buf []byte) (n int, err error)
Write(buf []byte) (n int, err error)
}
第二个接口位于另一个包中:
package two
type IStream interface {
Write(buf []byte) (n int, err error)
Read(buf []byte) (n int, err error)
}
这里我们定义了两个接口,一个叫one.ReadWriter,一个叫two.Istream,两者都定义
了Read()、Write()方法,只是定义次序相反。one.ReadWriter先定义了Read()再定义了
Write(),而two.IStream反之。
在Go语言中,这两个接口实际上并无区别,因为:
1 任何实现了one.ReadWriter接口的类,均实现了two.IStream;
2 任何one.ReadWriter接口对象可赋值给two.IStream,反之亦然;
3 在任何地方使用one.ReadWriter接口与使用two.IStream并无差异。
以下这些代码可编译通过:
var file1 two.IStream = new(File)
var file2 one.ReadWriter = file1
var file3 two.IStream = file2
接口赋值并不要求两个接口必须等价。如果接口A的方法列表是接口B的方法列表的子集,
那么接口B可以赋值给接口A。例如,假设我们有Writer接口:
type Writer interface {
Write(buf []byte) (n int, err error)
}
就可以将上面的one.ReadWriter和two.IStream接口的实例赋值给Writer接口:
var file1 two.IStream = new(File)
var file4 Writer = file1
但是反过来并不成立:
var file1 Writer = new(File)
var file5 two.IStream = file1 // 编译不能通过
这段代码无法编译通过,原因是显然的:file1并没有Read()方法。
go语言之接口一的更多相关文章
- R语言数据接口
		
R语言数据接口 R语言处理的数据一般从外部导入,因此需要数据接口来读取各种格式化的数据 CSV # 获得data是一个数据帧 data = read.csv("input.csv" ...
 - [日常] Go语言圣经--接口约定习题
		
Go语言圣经-接口1.接口类型是对其它类型行为的抽象和概括2.Go语言中接口类型的独特之处在于它是满足隐式实现的3.Go语言中还存在着另外一种类型:接口类型.接口类型是一种抽象的类型4.一个类型可以自 ...
 - FFI (语言交互接口(Foreign Function Interface))
		
FFI(Foreign Function Interface)是用来与其它语言交互的接口, 在有些语言里面称为语言绑定(language bindings), Java 里面一般称为 JNI(Java ...
 - C语言原子接口与实现
		
原子是一个指向唯一的.不可变的0个或任意多个字节序列的指针,大多数原子都是指向以空字符结束的字符串,但是任何一个指向任意字节序列的指针都可以使原子.任何原子只能出现一次.如果两个原子指向同一个内存单元 ...
 - c语言调试接口
		
http://blog.chinaunix.net/uid-10106787-id-2985587.html 在C语言程序设计中,常会出现各种各样的bug:段错误.参数异常等等.我们需要尽快定位错误, ...
 - Java语言Socket接口用法详解
		
Socket接口用法详解 在Java中,基于TCP协议实现网络通信的类有两个,在客户端的Socket类和在服务器端的ServerSocket类,ServerSocket类的功能是建立一个Serve ...
 - Go语言的接口
		
一.接口的定义和好处 我们都知道接口给类提供了一种多态的机制,什么是多态,多态就是系统根据类型的具体实现完成不同的行为. 以下代码简单说明了接口的作用 package main import ( &q ...
 - go语言学习-接口
		
Go语言中虽然没有传统面向对象语言中类.集成的概念,不过提供了接口的支持,可以使用接口来使用一些面向对象的特性. 在 go 语言中,的接口有下面几个特点: 可以包含0个或多个方法的签名 只定义方法的签 ...
 - Go语言的接口interface、struct和组合、继承
		
Go语言的interface概念相对于C++中的基类,通过interface来实现多态功能. 在C++中,当需要实现多态功能时,步骤是首先定义一个基类,该基类使用虚函数或者纯虚函数抽象了所有子类会用到 ...
 - Go语言的接口与反射
		
美女图片没啥用,就是为了好看 本文还在完善中... go总体而言是一门比较好入门的语言,许多特性都很精简易懂,但是接口与反射除外.他们真的让人头疼,不知道是自身资质问题还是怎么着,总是觉得很多书上写的 ...
 
随机推荐
- 如何使用CodeSmith批量生成代码
			
在上一篇我们已经用PowerDesigner创建好了需要的测试数据库,下面就可以开始用它完成批量代码生成的工作啦. 下面我会一步步的解释如何用CodeSmith实现预期的结果的,事先声明一下,在此只做 ...
 - 【Xcode学C-3】if等流程控制、函数的介绍说明标记分组、#include以及LLVM
			
一.流程控制:if.while和for循环 (1)if括号中面常常遇到推断是否相等的情况,并且新手常常会把==写成=.所以建议的习惯是把常量放在前面.如a==10.写成10==a,这样就不易犯错. ( ...
 - Nginx探索三
			
这次探索一下http 请求 request 这节我们讲request,在nginx中我们指的是http请求,详细到nginx中的数据结构是ngx_http_request_t. ngx_http_re ...
 - zabbix客户端安装shadowscoks客户端监控访问google网站
			
配置zabbix客户端配置文件 vim /etc/zabbix/zabbix_agentd.conf 添加 Include=/etc/zabbix/zabbix_agentd.d/ 添加脚本探测访问 ...
 - 操作符(运算符)重载  或者叫 二元运算符    operator +   与  转换式操作符  implicit operator    explicit operator
			
static void Main(string[] args) { rational r1 = new rational(5); rational r2 = new rational(51); rat ...
 - MongoDB启动及用户名密码设置
			
1.服务启动 下载后的安装步骤,请参见mongoDB安装详细教程 启动服务NET START MongoDB 关闭服务NET STOP MongoDB 启动客户端mongo MongoDB shell ...
 - shell统计一个文件里某行出现的次数并排序
			
话说有个aaa.txt文件,文件内容如下: aaaabbbbccccddddeeeeffffmmmmooooaaaaccccaaaabbbbddddaaaammmmbbbbaaaaoooo 然后面试题 ...
 - 介绍C#结构体与类区别
			
1. 结构体与类定义方式 结构体定义使用struct类定义使用class 结构体: struct testDemo{ int num; void action(){ } } 类: class test ...
 - 自己动手开发IOC容器
			
前两天写简历.写了一句:精通Spring IoC容器.怎么个精通法?还是自己动手写个IOC容器吧. 什么是IoC(Inversion of Control)?什么是DI(Dependency Inje ...
 - 连接redis失败,关闭防火墙即可
			
因为linux上有防火墙,我用redis desktop manager 测试所以始终连接不上, 关闭防火墙: systemctl stop firewalld.service #停止firewall ...