go——接口
Go语言提供了另外一种数据类型,即接口,它把所有具有共性的方法定义在一起,
任何其它类型只要实现了这些方法就是实现了这个接口。
接口代表一种调用契约,是多个方法声明的集合。
在某些动态语言里,接口(interface)也被称作协议(protocol)。
准备交互的双方,共同遵守事先约定的规则,使得无须知道对方身份的情况下进行协作。
接口要实现的是做什么,而不关心怎么做,谁来做。
接口解除了类型依赖,有助于减少用户可视方法,屏蔽内部结构和实现细节。
似乎好处很多,但这并不意味着可以滥用接口,毕竟接口实现机制会有运行开销。
对于相同包,或者不会频繁变化的内部模块结构,并不需要抽象出接口来强行分离。
接口最常见的使用场景是对包外提供访问,或预留扩展空间。
Go的接口类型用于定义一组行为,其中每个行为都由一个方法声明表示。
接口类型中的方法声明只有方法签名而没有方法体,而方法签名包括且仅包括方法的名称、参数列表和结果列表。
举个例子,如果要定义“聊天”相关的一组行为,可以这样写:
type Talk interface {
Hello(userName string) string
Talk(heard string) (saying string,end bool,err error)
}
type、接口类型名称、interface以及由花括号包裹的方法声明集合,共同组成了一个接口类型声明。
注意,其中每个方法声明必须独占一行。
只要一个数据类型的方法集合中包含Talk接口声明的所有方法,那么它就一定是Talk接口的实现类型。
//定义接口
type interface_name interface {
method_name1 [return_type]
method_name2 [return_type]
method_name3 [return_type]
...
method_namen [return_type]
} //定义结构体
type struct_name struct {
/**/
} //实现接口方法
func (struct_name_var struct_name) method_name1() [return_type] {
/*方法实现*/
} func (struct_name_var struct_name) method_name2() [return_type] {
/*方法实现*/
}
简单实例:
package main import (
"fmt"
) //定义一个Phone接口
type Phone interface {
call() //接口中有一个call方法
} //定义诺基亚结构体
type NokiaPhone struct {
}
//实现call方法
func (nokkiaPhone NokiaPhone) call() {
fmt.Println("I am Nokia")
} //定义苹果结构体
type Iphone struct {
}
//实现call方法
func (iphone Iphone) call() {
fmt.Println("I am iphone")
} func main() {
//根据接口声明变量
var phone Phone //同一个接口变量就能实现多个结构体中的方法
phone = new(NokiaPhone) //创建一个指定类型的值,并返回该值的指针
phone.call() phone = new(Iphone)
phone.call()
} /*
I am Nokia
I am iphone
*/
编译器会根据方法集来判断是否实现了接口。
如果接口没有任何方法声明,那么就是一个空接口(interface{}),
它的用途类似面向对象里面的根类型Object,可被赋值为任何类型的对象。
接口变量默认值是nil,如果实现接口的类型支持,可做相等运算。
package main
import "fmt"
type tester interface {
test() string
string() string
}
type data struct{} //定义结构体
func (*data) test() string {
return "5678"
} //实现test方法
func (data) string() string { //实现string
return "aaaaaaaaa"
}
func main() {
var d data
var t tester = &d //
fmt.Println(t.test()) //不论是data和*data都是指代同一个程序实体
fmt.Println(t.string())
}
可以像匿名字段那样,嵌入其它接口。
目标类型方法集中必须拥有包含嵌入接口方法在内的全部方法才算实现了该方法。
嵌入其它接口类型,相当于将其声明的方法集导入。
这就要求不能有同名方法,因为不支持重载。还有,不能嵌入自身或循环嵌入,那会导致递归错误。
package main
import "fmt"
type stringer interface {
string() string
}
type tester interface {
test() string
stringer
}
type data struct{} //定义结构体
func (*data) test() string {
return "5678"
} //实现test方法
func (data) string() string {
return "aaaaaaaaa"
}
func main() {
var d data
var t tester = &d //
fmt.Println(t.test())
fmt.Println(t.string())
}
package main
import "fmt"
type stringer interface {
string() string
}
type tester interface {
test() string
stringer
}
type data struct{}
func (*data) test() string {
return "5678"
}
func (data) string() string {
return "aaaaaaaaa"
}
func pp(a string) {
fmt.Println(a.string())
}
func main() {
var d data
var t tester = &d
pp(t)
var s stringer = t
fmt.Println(s.string())
}
支持匿名接口类型,可直接用于变量定义,或作为结构字段类型。
package main
import "fmt"
type data struct{} //结构体data
func (data) string() string {
return "123456"
}
type node struct {
data interface { //字段类型为接口
string() string
}
}
func main() {
var t interface { //变量t为接口类型
string() string
} = data{} //空结构体
n := node{
data: t,
}
fmt.Println(n.data.string()) //123456
}
类型推断可将接口变量还原为原始类型,或用来判断是否实现了某个更具体地接口类型。
package main
import "fmt"
type data int
func (d data) String() string { //方法
return fmt.Sprintf("data:%d", d)
}
func main() {
var d data = 15
var x interface{} = d
if n, ok := x.(fmt.Stringer); ok {
fmt.Println(n)
}
if d2, ok := x.(data); ok {
fmt.Println(d2)
}
e := x.(error)
fmt.Println(e)
}
/*
data:15
data:15
panic: interface conversion: main.data is not error: missing method Error
*/
go——接口的更多相关文章
- App开发:模拟服务器数据接口 - MockApi
为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块.本篇文章就尝试为使用gradle的android项目设计实现Moc ...
- 干货来袭-整套完整安全的API接口解决方案
在各种手机APP泛滥的现在,背后都有同样泛滥的API接口在支撑,其中鱼龙混杂,直接裸奔的WEB API大量存在,安全性令人堪优 在以前WEB API概念没有很普及的时候,都采用自已定义的接口和结构,对 ...
- 12306官方火车票Api接口
2017,现在已进入春运期间,真的是一票难求,深有体会.各种购票抢票软件应运而生,也有购买加速包提高抢票几率,可以理解为变相的黄牛.对于技术人员,虽然写一个抢票软件还是比较难的,但是还是简单看看123 ...
- Java基础Map接口+Collections工具类
1.Map中我们主要讲两个接口 HashMap 与 LinkedHashMap (1)其中LinkedHashMap是有序的 怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...
- Java基础Map接口+Collections
1.Map中我们主要讲两个接口 HashMap 与 LinkedHashMap (1)其中LinkedHashMap是有序的 怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...
- java基础_集合List与Set接口
List接口继承了Collection的方法 当然也有自己特有的方法向指定位置添加元素 add(索引,添加的元素); 移除指定索引的元素 remove(索引) 修改指定索引的元素 set ...
- 【WCF】自定义错误处理(IErrorHandler接口的用法)
当被调用的服务操作发生异常时,可以直接把异常的原始内容传回给客户端.在WCF中,服务器传回客户端的异常,通常会使用 FaultException,该异常由这么几个东东组成: 1.Action:在服务调 ...
- PHP以接口方式实现多重继承(完全模拟)--学习笔记
1.UML类图: 2.PHP代码: <?php /** * Created by PhpStorm. * User: andy * Date: 16-11-23 * Time: 下午7:57 ...
- 【微框架】Maven +SpringBoot 集成 阿里大鱼 短信接口详解与Demo
Maven+springboot+阿里大于短信验证服务 纠结点:Maven库没有sdk,需要解决 Maven打包找不到相关类,需要解决 ps:最近好久没有写点东西了,项目太紧,今天来一篇 一.本文简介 ...
- 【接口开发】浅谈 SOAP Webserver 与 Restful Webserver 区别
接口,强大,简单,交互,跨越平台 下面简单阐述这两大接口思想 一 REST: REST是一种架构风格,其核心是面向资源,REST专门针对网络应用设计和开发方式,以降低开发的复杂性,提高系统的可伸缩性. ...
随机推荐
- TCP/IP详解读书笔记:ARP-地址解析协议
地址解析为两种不同的地址形式提供映射:32bit的IP和数据链路层使用的任何类型的地址. 当一台主机把以太网数据帧发送到位于同一局域网的另一台主机,是根据48bit的以太网地址而不是IP地址.设备驱动 ...
- Acme Corporation UVA - 11613 拆点法+最大费用最大流(费用取相反数)+费用有正负
/** 题目:Acme Corporation UVA - 11613 拆点法+最大费用最大流(费用取相反数)+费用有正负 链接:https://vjudge.net/problem/UVA-1161 ...
- ES6快速入门使用
https://www.jianshu.com/p/061304806bda Babel-webpack的配置 Bebal官方文档 前段项目我想使用ES6的语法我应该怎么做呢?我们可以查看Babel的 ...
- 【Raspberry Pi】读取DHT11温度湿度波折
从网上找到了DHT11厂家说明书,尝试用python根据时序图写数据获取驱动,但发现python的高层特性导致在做底层代码时例如控制20us时延这类需求就没什么好的办法. 还是得回到C-wiringP ...
- 【Python】求素数-稍加优化
print 'Find prime number smaller then input number \n' print 'Please input a number:' import datetim ...
- <input>type类型
当Input框需要输入数字时,一般用到type='number' 但是在输入框有 上下小箭头 google后有解决CSS方案 在chrome下: input::-webkit-outer-spin-b ...
- django用户认证系统——重置密码7
当用户不小心忘记了密码时,网站需要提供让用户找回账户密码的功能.在示例项目中,我们将发送一封含有重置用户密码链接的邮件到用户注册时的邮箱,用户点击收到的链接就可以重置他的密码,下面是具体做法. 发送邮 ...
- java动态编译 (java在线执行代码后端实现原理)
需求:要实现一个web网页中输入java代码,然后能知道编译结果以及执行结果 类似于菜鸟java在线工具的效果:https://c.runoob.com/compile/10 刚开始从什么概念都没有到 ...
- sass学习之一:sass安装compass部署
主要参考 http://www.jianshu.com/p/5bfc9411f58f -------------------------------------------- sass基于ruby 需 ...
- 指定运行Exchange Powershell的Server
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -command ". 'C:\Program Files ...