参考 Understanding Go Interface

感谢 francesc 分享

接口

我们编程中少不了对接口使用和设计,无论你是使用哪种语言或多或少都会使用到**接口**。即使你说明重来没有显示定义过或者使用过接口,我想如果你也可能隐式地用到过接口。

今天我们就说一说 go 语言中的接口是如何设计的;如何使用的以及他与其他语言相比有什么自己的特点。

什么是 interface

接口可以理解是规范、协议、用户使用手册和对类型抽象,对行为描述。说了这么一大堆还需要您自己了解。

> In object-oriented programming, a protocal or interface is a common means for unrelated objects to communicate with each other

wikipedia

上面的话摘字 wiki,这里传递了两个重要的信息

- communicate 接口是用于通讯,接口就是用来定义通讯遵循的规则,类似一种协议。

- unrelated objects 耦合度低的对象,接口定义通讯规则可以使用两个互不相干的对象。通过接口会将关注点放在交流上,而不会关注与通讯无关的类型上。

乐高玩具就是一个好的例子。乐高玩具的一个piece 组合时只要遵守尺寸规则,无论大小和颜色就可以组合在一起进行拼接。

以后兼职工作也是一样只要满足规定的条件,在拼接 Lego 玩具时是否可以拼接是和piece 的颜色和形状没有关系的,只要他们都遵守一定尺寸就可以进行拼接。在软件控制模块搭建和通讯也是通过定义一定接口规范来实现了。我想软件工程也在某些方面借鉴传统的行业。

想到 go 我们就会自然联想到他一个项目 docker,也就是 docker 项目让我们看 go 语言的商业化,docker 可以算上是 go 的最佳实践之一了。

之所以集装箱海运如何兴旺,因为提供一个统一接口,无论是什么样船或者是列车都可以可以运输集装箱,因为集装箱提供一种标准(接口)标准的尺寸和重量。

docker 设计也是源于集装箱设计,我们将 code 进行包装,然后提供一致接口这样我们的 code 就可以运行在任何符合其标准的环境了。

### 什么是 go 的 interface

在 go 语言中我们可以通过两个维度对类型进行划分

  • - 抽象类型

  • - 实体类型

当然在 go 语言中有很多种类型,不过我们大致可以将归为两种一种类型属于 abstract 类型(抽象类型)和 concrete 类型(实体类型)

实体类型

- 用于描述类型在内存中分配情况,根据类型我们就可以知道其在内存中存在形式。

int8/int16/int32/int64/struct/float

- 使用方法赋予数据一定的行为

type Number intfunc (n Number) Positive() bool{  return n >0}

抽象类型

这种类型就是接口,并不是说明类型的形状,而是告诉你能够使用这种类型来做什么。

抽象类型并没定义描述如何为这种类型分配内存空间,而是描述类型的行为。按行为为类型进行划分。这些抽象类型有 io.Reader 、 io.Writer 和 fmt.String 等等

type Positiver interface{  Positive() bool}

在 Positiver 接口中定义了 Positive 这里大家已经注意到了我们并没有指定接口的接收者(也就是实现者)。这就是 go 语言设计初衷,也就是我不关心你是什么类型只要你有一个形状(包括函数名、参数和返回值)一致的方法,我就认为你是实现了这个接口,你属于这个类型。

用来说明 go 语言接口的经典接口 Writer 和 Reader 接口

type Reader interface{  Read(b []byte)(int,error)}type Writer interface{  Write(b []byte)(int,error)}

只要实现了接口的方法的类型就属于接口类型,所以集合是实体类型的集合。

接口的组合

type ReadWriter interface{  Read  Writer}

接口是可以组合,这个 ReadWriter 接口,当然实现这个接口类型应该是更强大而范围从图上来看却缩小了。但是接口越详细确定范围也就小。

interface{}

这里有一个 interface{} , Rob Pike 指着 interface{} 是没有任何意思,因为没有任何限制,没有限制也就是没有意义,这个应该不难理解。在 go 语言中可以用 interface 表示类型,但是从 interface{} 来看我们是无法了解其代表类型的具体信息。

使用接口原因

  • - 编写通用的算法

  • - 隐藏实现的细节

  • - 提供拦截点

以上三点是我们使用接口原因,这里逐一给大家进行讲解。

a) func writeTo(f *os.File) error

b) func writeTo(w *os.ReadWriteCloser) error

c) func writeTo(w io.Writer) error

d) func writeTo(w interface{}) error

上面选择题您选择哪个?

答案是 b 或 c,a 选项问题是这里接收一个实体类型作为参数,这样对于测试 writeTo 就造成问题,我们每次测试这个方法就需要实例化一个 File 对象,这样得不偿失。

d 答案是对参数没有任何限制,从而也就是失去意义。没有任何关于类型有价值的信息,编译器也不会进行类型检查的。

b 和 c 根据你应用场景而定,接口的方法越少,复用性就越高。

> The bigger the interface, the weaker the abstraction

rob pike

> Be conservative in what you do, be liberal in what you accept from others

这是一条 robustness 理论,这句话源于 TCP 网络协议,在 TCP 网络协议是遵循发送到网络上数据是没有问题的,而从网络上接收数据即使有问题也是可以接受的。

### 抽象数据类型

数据类型的数学模型

通过下面依据来定义数据的行为

  • - 需要考虑数据可能的值

  • - 对此类型数据的可能操作

  • - 这些操作的行为

我们看一看栈这个抽象数据模型,有什么行为

top(push(x,s)) = x

我们 push 数据 x 入栈 s 然后用 top 方法进行出栈就会得到 x,逻辑性很强吧

pop(push(x,s)) = s

我们 push 数据 x 入栈 s 然后用 pop 弹出会返回栈进行push 前的 s。

empty(new())not empty(push(s,x))

通过上面分析我们就得到数据模型 stack

top(push(x,s)) = xpop(push(x,s)) = sempty(new())!empty(push(s,x))

这个比较抽象,我们通过定义一些行为来表述一种数据结构,理解起来可能会话费一段时间,可以通过行为表述抽象数据结构,例如先进先出就是数据结构。我们用行为表述了 stack 这一抽象数据。

接下来在 go 语言中,用具体代码对上面描述进行接口定义来表述 stack 抽象数据结构。

type Stack interface{  Push(v interface{}) Stack  Pop() Stack  Empty() bool}

在抽象数据结构上我们可以定义一些算法,这里 Size 算法需要传入抽象数据结构具有 Empty() 和 Pop() 行为,而且 Size 算法并不关系实现了这两个方法的类型的详细信息。这要实现了这两个方法即可。

func Size(s Stack) int {  if s.Empty(){    return 0  }  return Size(s.Pop()) + 1}

通过定义可排序的数据结构

type Interface interface{  Less(i,j int) bool  Swap(i, j int)  Len() int}

到现在大家可能有一些了解了在 go 语言中使用接口套路,我们先根据抽象数据结构可能有的操作,来推断出这些操作的行为。在这些抽象数据结构上定义一些通用算法,这些算法接收接口作为参数,只要这些类型提供其算法所需要的行为就行。看一看我们在 Writer 和 Reader 上的一些算法。

func Fprintln(w Writer, ar ...interface{}) (int,error)func Fscan(r Reader, a ...interface{}) (int, error)func Copy(w Writer, r Reader)(int, error)

我们可以在接口上写通用方法

现在我们明白之前说的那句话了吧,我们只是提供对的,对于接收的我们只是接收就好了。

这个选择题可以帮助你判断是否对上面所讲已经理解了。

  • a) func New() *os.File

  • b) func New() io.ReadWriteCloser

  • c) func New() io.Writer

  • d) func New() interface{}

首先我们来排除 d ,因为 interface{} 是没有任何意义和帮助的。b 和 c 也没有什么区别只是限制用户使用范围,如果只想让用户有写的能力就可以用 io.Writer 。最佳答案是 a,因为 robustness 原则是我们给出应该是好的确定的所以应该是 *os.File 实体类型而非仅是限制用户的接口。

那么我们终结一下 go 语言程序 robuness 的原则吧

返回给用户(这里用户是函数调用者)应该是确定的实体类型,而接收参数应该是接口

interface接口_golang 基础(Four) 接口进阶相关推荐

  1. typescript 接口 java_Typescript基础(4)——接口

    前言 今天继续typescript的学习,开始ts接口部分的学习. 接口 接口的理解 首先,我们谈论一下现实生活中的接口.比如生活中常用的插座接口,有些插头是三孔插座的,有些是两孔插座的.插座接口规定 ...

  2. Java基础-面向接口(interface)编程

    Java基础-面向接口(interface)编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.接口的概念 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的&q ...

  3. Java接口的基础语法(interface)(超详细!)

    1.接口也是一种"引用数据类型".编译之后也是一个class字节码文件. 2.接口是 完全抽象 的(无法实例化).(抽象类是半抽象.)或者也可以说接口是特殊的抽象类. 3.接口怎么 ...

  4. 关于接口的基础到进阶你要知道的知识

    想了很久,闲来无事,今天想了下还是总结了下写下来,部分参考官方源码理解,还有就是这么久的理解, 如果觉得有帮助请记得点赞 先讲下接口url组成拿后台服务为例 通常一个后台请求url格式: http:/ ...

  5. 接口的基础语法和接口在开发中的作用2021-07-23java学习日记

    Javase进阶 接口的语法和接口的作用 p499-p516 关键词: 接口    implements    面向抽象编程    OCP开闭原则 接口的基础语法 1.接口也是一种引用数据类型,编译之 ...

  6. Servlet基础:接口、类、请求响应、配置、会话追踪、上下文、协作、异常

    10.1 Servlet介绍 ​ Servlet技术是Sun公司提供的一种实现动态网页的解决方案,它是基于Java编程语言的Web服务器端编程技术,主要用于在Web服务器端获得客户端的访问请求信息和动 ...

  7. TypeScript基础入门 - 接口 - 继承接口

    转载地址 TypeScript基础入门 - 接口 - 继承接口 项目实践仓库 https://github.com/durban89/typescript_demo.git tag: 1.0.13 为 ...

  8. 这样设计是否更好些~仓储接口是否应该设计成基础操作接口和扩展操作接口

    前言 我们进行linq to sql和ef时代后,底层的实现基本使用的是repository模块,即仓储模式,事实上就是把ORM实体的最基本操作进行封闭,对外层不公开操作实现的细节. 面向接口的编程 ...

  9. TypeScript基础入门 - 接口 - 可索引的类型

    转载地址 TypeScript基础入门 - 接口 - 可索引的类型 项目实践仓库 https://github.com/durban89/typescript_demo.git tag: 1.0.11 ...

最新文章

  1. 终于把 7 年前的 Docker Hub 账号恢复了
  2. linux lddbus设备,Linux那些事儿之我是Sysfs(4)举例一lddbus | 技术部落
  3. 疾风之刃的最新服务器,《疾风之刃》服务器数据互通(合服)提前预览
  4. 介绍“Razor”— ASP.NET的一个新视图引擎
  5. [APIO2009]抢掠计划
  6. cross apply
  7. 敏捷开发中史诗故事与用户故事的颗粒度
  8. 毕业多年没稳定的收入...大龄转行做自动化测试,现在已经快年薪30W
  9. Quartus ii仿真界面闪退
  10. kuangbin专题五并查集总结
  11. Linux的LCD驱动
  12. 短基线(SBL)定位原理及误差模型分析
  13. 期权、期货及其他衍生产品 第三章读书笔记 利用期货的对冲策略
  14. Centos5反p2p模块安装精要
  15. 多年来被互联网深深洗脑
  16. Excel学习1:图表配色
  17. Devc++使用及debug超详解
  18. apr 移植android平台,omap3530移植android4.0
  19. 微信客服消息跳转h5,回复关键字,跳转小程序方式全集
  20. 低档计算机配置 新闻,一台电脑配置的高低,主要看这四方面

热门文章

  1. python小白逆袭大神课程心得_Python小白逆袭大神学习心得
  2. keycloak mysql_Keycloak换mysql存储详细步骤
  3. oracle bi publisher 安装,Oracle BI Publisher 企业版安装后的配置(BI Publisher Enterpr
  4. Linux之Less命令跳转到特定的行号
  5. 程序员,感觉技术停滞了怎么办?
  6. 虚拟机ubuntu启动代码界面_Windows10下使用虚拟机安装Ubuntu18.04
  7. 如何重置linux,linux如何重置服务器
  8. html用户登录界面开源代码_Toolkit Pro助力企业开专业且强大的图形用户界面,抢占市场先机...
  9. vlc web 登录账号_怎么在web网页端解绑敬业签绑定的手机号?
  10. Java自带的广告怎么删掉_如何屏蔽电脑上的弹窗广告?