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. JavaScript绘图类 (DIV绘图)

    主要的图形算法抄自一个叫w_jsGraphics.js的类库,第一次看到那个库的时候,感觉那是十分神奇的存在.不过估计现在那个库早就已经找不到了. 这是很早之前的一个DIV绘图类,那时候VML+SVG ...

  2. PHP——smarty模板(第一天)

    smarty.class.php 主要的东西放在类里面templates 放模板templates_c 放缓存 类里面 $smarty->assign("author",&q ...

  3. git版本管理之git-ssh 配置和使用

    1.设置用户名和邮箱 $ git config --global user.name "gsx-gh" $ git config --global user.email " ...

  4. eclipse中根据方法找到其实现类

    面向接口编程中,程序全是面向接口变成调用,在维护别人写的系统的时候怎么样快速定位当前根据接口调用的方法是哪个实体类实现的: Ctrl + T/f4(光标放在需要查看的方法上,然后按Ctrl+T或者F4 ...

  5. C++ 类模板三(类模版中的static关键字)

    //类模版中的static关键字 #include<iostream> using namespace std; /* 类模板本质上是c++编译器根据类型参数创建了不同的类, c++编译器 ...

  6. sklearn解决分类问题(KNN,线性判别函数,二次判别函数,KMeans,MLE,人工神经网络)

    代码:*******************加密中**************************************

  7. 《转》openstack中删除虚拟主机,状态一直deleting

    一.我重新启动了该机器.之后想删除没有创建成功的虚拟机(没有打开cpu的vt).结果发现状态一直为deleting状态.在这个状态下创建虚拟机也失败. 二.分析:在/var/log/nova/nova ...

  8. 解决在SharePoint 2010/2013部署自己的Event Handler后,抛出”不能载入被引用的第三方的程序集&quot;的问题

    今天在处理客户的一个问题的时候.我们已经把我们SharePoint EventHandler依赖的第三方的TIBCO.EMS.dll注冊到GAC里面了,可是日志里面还是抛出了不能载入被引用的第三方的程 ...

  9. js Date操作

    new Date(new Date().getTime() - 24 * 24 * 60 * 60 * 1000)类似C#中的AddDays,返回一个月前的时间  //时间格式化方法        v ...

  10. 非阻塞IO 和阻塞IO【转】

    IO模式设置网络编程常见问题总结—IO模式设置,阻塞与非阻塞的比较,recv参数对性能的影响—O_NONBLOCK(open使用).IPC_NOWAIT(msgrcv).MSG_DONTWAIT(re ...