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——接口的更多相关文章

  1. App开发:模拟服务器数据接口 - MockApi

    为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块.本篇文章就尝试为使用gradle的android项目设计实现Moc ...

  2. 干货来袭-整套完整安全的API接口解决方案

    在各种手机APP泛滥的现在,背后都有同样泛滥的API接口在支撑,其中鱼龙混杂,直接裸奔的WEB API大量存在,安全性令人堪优 在以前WEB API概念没有很普及的时候,都采用自已定义的接口和结构,对 ...

  3. 12306官方火车票Api接口

    2017,现在已进入春运期间,真的是一票难求,深有体会.各种购票抢票软件应运而生,也有购买加速包提高抢票几率,可以理解为变相的黄牛.对于技术人员,虽然写一个抢票软件还是比较难的,但是还是简单看看123 ...

  4. Java基础Map接口+Collections工具类

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  5. Java基础Map接口+Collections

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  6. java基础_集合List与Set接口

    List接口继承了Collection的方法  当然也有自己特有的方法向指定位置添加元素   add(索引,添加的元素); 移除指定索引的元素   remove(索引) 修改指定索引的元素   set ...

  7. 【WCF】自定义错误处理(IErrorHandler接口的用法)

    当被调用的服务操作发生异常时,可以直接把异常的原始内容传回给客户端.在WCF中,服务器传回客户端的异常,通常会使用 FaultException,该异常由这么几个东东组成: 1.Action:在服务调 ...

  8. PHP以接口方式实现多重继承(完全模拟)--学习笔记

     1.UML类图: 2.PHP代码: <?php /** * Created by PhpStorm. * User: andy * Date: 16-11-23 * Time: 下午7:57 ...

  9. 【微框架】Maven +SpringBoot 集成 阿里大鱼 短信接口详解与Demo

    Maven+springboot+阿里大于短信验证服务 纠结点:Maven库没有sdk,需要解决 Maven打包找不到相关类,需要解决 ps:最近好久没有写点东西了,项目太紧,今天来一篇 一.本文简介 ...

  10. 【接口开发】浅谈 SOAP Webserver 与 Restful Webserver 区别

    接口,强大,简单,交互,跨越平台 下面简单阐述这两大接口思想 一 REST: REST是一种架构风格,其核心是面向资源,REST专门针对网络应用设计和开发方式,以降低开发的复杂性,提高系统的可伸缩性. ...

随机推荐

  1. golang mongodb查找find demo

    使用gopkg.in/mgo.v2库操作,插入操作主要使用mongodb中Collection对象的Find方法,函数原型: func (c *Collection) Find(query inter ...

  2. 使用BarcodeLib.Barcode.ASP.NET生成条形码

    生成条形码图片,然后在前台页面展示: <img id="img" src="Mobile/<%=url %>"/> public str ...

  3. noip模拟题题解集

    最近做模拟题看到一些好的题及题解. 升格思想: 核电站问题 一个核电站有N个放核物质的坑,坑排列在一条直线上.如果连续M个坑中放入核物质,则会发生爆炸,于是,在某些坑中可能不放核物质. 任务:对于给定 ...

  4. opencv2.4.9+VS2010配置

    opencv2.4.9 https://pan.baidu.com/s/15b5bEY65R4CptayEYVAG4A 安装包路径:D:\文件及下载相关\文档\Tencent Files\845235 ...

  5. vue-infinite-scroll 自动加载

    初次上手vue开发 笑话百出,各种麻爪 在实现上拉加载的时候用的是mint-ui里面的 infinite-scroll 结果在使用的时候不停的自动加载,后来查询了相关资料 原来是控件识别只要没有铺满全 ...

  6. 【BZOJ2055】80人环游世界 有上下界费用流

    [BZOJ2055]80人环游世界 Description     想必大家都看过成龙大哥的<80天环游世界>,里面的紧张刺激的打斗场面一定给你留下了深刻的印象.现在就有这么     一个 ...

  7. C++名人的网站 转

    正如我们可以通过计算机历史上的重要人物了解计算机史的发展,C++相关人物的网站也可以使我们得到最有价值的参考与借鉴. 正如我们可以通过计算机历史上的重要人物了解计算机史的发展,C++相关人物的网站也可 ...

  8. oracle批量update

    我个人觉得写的很好 http://blog.csdn.net/wanglilin/article/details/7200201 需求: 将t2(t_statbuf)表中id和t1(T_Mt)表相同的 ...

  9. 【微信】QQ邮箱助手不提醒解决

    1.问题及原因: 微信上的QQ邮箱提醒功能失效了,收到信后不提醒.忘了是使用了TIM,还是使用了QQ邮箱之后才出现的. 不过原因是:QQ邮箱提醒被设置为仅在QQ邮箱客户端提醒 2.解决: 重新安装QQ ...

  10. 在Editplus中Dev C++配置C++的编译运行环境

    1.首先得下载安装DEV-cpp 2.打开Editplus编辑器,工具->配置自定义工具 3.具体配置 编译C:命令:D:\Dev-Cpp\MinGW64\bin\g++.exe参数:" ...