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. flutter 环境

    以下内容copy 于 https://www.cnblogs.com/lovelyYakir/p/7610396.html 原文请参考此 我只是做个记录 第一步:安装Git 你需要安装Git作为Flu ...

  2. cobbler setting dnsmasq

    Currently cobbler can help generate a ISC DHCP configuration (package name: dhcpd) it can also alter ...

  3. SQL Server跨server之间訪问

    在两个server都须要启用Ad Hoc Distributed Queries: EXEC sp_configure 'show advanced options', 1 RECONFIGURE E ...

  4. asp.net调用系统设置字体文本框的方法

    本文实例展示了asp.net调用系统设置字体文本框的方法,是进行web开发中很实用的技巧.具体实现步骤如下: 一.调用系统字体文本框 首先在bin文件夹右击-->添加引用-->.net标签 ...

  5. MathType编辑钢筋符号就是这么简单

    很多的用户在使用MathType公式编辑器的时候,发现它所包含的符号非常的多,几乎你在数学中看到的任何符号都能用MathType编辑出来.它能够满足各个学科对符号的需求,除了常规的数学物理符号之外,也 ...

  6. Extjs4 中date时间格式的问题

    在Grid中显示时间,后台传过来的是date格式的数据(PHP date('Y-m-d', time()),一般在Ext model中定义数据的类型和格式: {name:'birth', type:' ...

  7. java的junit測试

    在实际的开发中不仅须要断点调试.语句输出的方法进行程序的调试,也须要单元測试. 在java中的junit的測试方法通常是在要測试的方法上面加入@Test.@ Before.@After,@Before ...

  8. BZOJ 3261 最大异或和 可持久化Trie树

    题目大意:给定一个序列,提供下列操作: 1.在数组结尾插入一个数 2.给定l,r,x,求一个l<=p<=r,使x^a[p]^a[p+1]^...^a[n]最大 首先我们能够维护前缀和 然后 ...

  9. Python 构造函数、 Python 析构函数、Python 垃圾回收机制

    构造函数与析构函数 构造函数: 用于初始化类的内容部状态,Python提供的构造函数式 __init__(); 也就是当该类被实例化的时候就会执行该函数.那么我们就可以把要先初始化的属性放到这个函数里 ...

  10. Win8 IIS 安装和部署网站问题

    安装IIS 比较win7的安装来说,多选了几个钩钩,不然会报错,偶就遇到这样的错误. 控制面板->程序和功能->启动和关闭windows功能,钩钩图例: 安装好iis后 在控制面板-> ...