现在的位置: 首页 > 综合 > 正文

Rob pike 谈接口

2017年11月11日 ⁄ 综合 ⁄ 共 1251字 ⁄ 字号 评论关闭

Go里的接口真的非常、非常地简单。接口指明了两个不同事情:其一,它表明了类型的构思,接口类型是一个罗列了一组方法的类型,因此如果你要抽象一组方法来定义一个行为,那么就定义一个接口并声明这些方法。现在你就有了一个类型,我们就叫它接口类型吧,那么从现在起所有实现了接口中这些方法的类型——包括基本类型、结构、映射(map)或其它什么类型,都隐含符合该接口要求。其二,也是真正有意思的是,和大多数语言中的接口不同的是,Go里面没有“implements”声明。

你无须说明“我的对象实现了这个接口”,只要你定义了接口中的那些方法,它就自动实现了该接口。有些人对此感到非常担忧,依我看他们想说的是:知道自己实现(Implement)了什么接口真的很重要。如果你真想确定自己实现了什么接口,还是有技巧可以做到这一点的。但是我们的想法与此截然不同,我们的想法是你不应该考虑实现什么接口,而是应该写下要做的东西,因为你不必事前就决定要实现哪个接口。可能后来你实际上实现了某个现在你尚不知晓的接口,因为该接口还未设计出来,但是现在你已经在实现它。

后来你可能发现两个原先未曾考虑过相关性的类具有了相关性——我又用了类这个词,我思考Java太多了——两个structs都实现了一些非常有用的小子集中的相关方法,这时有办法能够操作这两个structs中的任意一个就显得非常有用了。这样你就可以声明一个接口,然后什么都不用管了,即使这些方法是在别人的代码中实现的也没问题,虽然你不能编辑这些代码。如果是Java,这些代码必须要声明实现你的接口,在某种意义上,实现是单向的。然而在Go里,实现是双向的。对于接口实际上有不少漂亮而简单的例子。

我最爱用的一个真实例子就是“Reader”,Go里有个包叫做IO,IO包里有个Reader接口,它只有一个方法,该方法是read方法的标准声明,比如从操作系统或文件中读取内容。这个接口可以被系统中任何做read系统调用的东西所实现。显然,文件、网络、缓存、解压器、解密机、管道,甚至任何想访问数据的东西,都可以给其数据提供一个Reader接口,然后想从这些资源中读取数据的任何程序都可以通过该接口达到目的。这有点像我们前面说过的Plan
9,但是用不同的方式泛化的。

与之类似,Writer也是比较好理解的另一个例子,Writer 由那些要做写操作的人来实现。那么在做格式化打印时,fpringf的第一参数不是file了,而是Writer。这样,fprintf可以给任何实现了write方法的东西做IO格式化的工作。有很多很好的例子:比如HTTP,如果你正在实现一个HTTP服务器,你仅须对connection做fprintf,便可将数据传递到客户端,不需要任何花哨的操作。你可以通过压缩器来进行写操作,你可以通过我所提到的任何东西来进行写操作:压缩器、加密机、缓存、网络连接、管道、文件,你都可以通过fprintf直接操作,因为它们都实现了write方法,因此,隐含都符合Writer接口要求。

抱歉!评论已关闭.