GO 接口

接口类型是对其它类型行为的抽象和概括;因为接口类型不会和特定的实现细节绑定在一起,通过这种抽象的方式我们可以让我们的函数更加灵活和更具有适应能力。

Go语言中接口类型的独特之处在于它是满足隐式实现的。 也就是说,我们没有必要对于给定的具体类型定义所有满足的接口类型;简单地拥有一些必需的方法就 足够了。这种设计可以让你创建一个新的接口类型满足已经存在的具体类型却不会去改变这些类型的定 义;当我们使用的类型来自于不受我们控制的包时这种设计尤其有用。

接口约定

接口类型是一种抽象的类型。它不会暴露出它所代表的 对象的内部值的结构和这个对象支持的基础操作的集合;它们只会展示出它们自己的方法。也就是说当 你有看到一个接口类型的值时,你不知道它是什么,唯一知道的就是可以通过它的方法来做什么。

接口类型

接口类型具体描述了一系列方法的集合,一个实现了这些方法的具体类型是这个接口类型的实例。

package io
 type Reader interface {
     Read(p []byte) (n int, err error)
}
 type Closer interface {
     Close() error
}

有些新的接口类型通过组合已经有的接口来定义。

type ReadWriter interface {
  Reader
  Writer
}
 type ReadWriteCloser interface {
   Reader
  Writer
  Closer
}

实现接口的条件

一个类型如果拥有一个接口需要的所有方法,那么这个类型就实现了这个接口。

var w io.Writer
w = os.Stdout // OK: *os.File has Write method
w = new(bytes.Buffer) // OK: *bytes.Buffer has Write method
w = time.Second // compile error: time.Duration lacks Write method
 
var rwc io.ReadWriteCloser
rwc = os.Stdout         // OK: *os.File has Read, Write, Close methods
rwc = new(bytes.Buffer) // compile error: *bytes.Buffer lacks Close method
w = rwc // OK: io.ReadWriteCloser has Write method
rwc = w  // compile error: io.Writer lacks Close metho

在T类型的参数 上调用一个T的方法是合法的,只要这个参数是一个变量;编译器隐式的获取了它的地址。但这仅仅是一 个语法糖:T类型的值不拥有所有*T指针的方法,那这样它就可能只实现更少的接口。例如:

type IntSet struct { /* ... */ }
 func (*IntSet) String() string
 var _ = IntSet{}.String() // compile error: String requires *IntSet receiver

但是我们可以在一个IntSet值上调用这个方法:

var s IntSet
 var _ = s.String() // OK: s is a variable and &s has a String method

由于只有IntSet类型有String方法,所有也只有IntSet类型实现了fmt.Stringer接口:

var _ fmt.Stringer = &s // OK
 var _ fmt.Stringer = s  // compile error: IntSet lacks String method

接口值

概念上讲一个接口的值,接口值,由两个部分组成,一个具体的类型和那个类型的值。它们被称为接口 的动态类型和动态值。

var w io.Writer
 w = os.Stdout
 w = new(bytes.Buffer)
 w = nil

一个接口值基于它的动态类型被描述为空或非空,所以这是一个空的接口值。你可以通过使用w==nil或 者w!=nil来判读接口值是否为空。调用一个空接口值上的任意方法都会产生panic:

w.Write([]byte("hello")) // panic: nil pointer dereference
w = os.Stdout
w.Write([]byte("hello")) // "hello"

这个赋值过程调用了一个具体类型到接口类型的隐式转换,这和显式的使用io.Writer(os.Stdout)是等价的。这类转换不管是显式的还是隐式的,都会刻画出操作到的类型和值。这个接口值的动态类型被设 为*os.Stdout指针的类型描述符,它的动态值持有os.Stdout的拷贝;
通常在编译期,我们不知道接口值的动态类型是什么,所以一个接口上的调用必须使用动态分配。因为不是直接进行调用,所以编译器必须把代码生成在类型描述符的方法Write上,然后间接调用那个地址。 这个调用的接收者是一个接口动态值的拷贝,os.Stdout。
接口值可以使用==和!=来进行比较。两个接口值相等仅当它们都是nil值或者它们的动态类型相同并 且动态值也根据这个动态类型的==操作相等。因为接口值是可比较的,所以它们可以用在map的键或者 作为switch语句的操作数。
然而,如果两个接口值的动态类型相同,但是这个动态类型是不可比较的(比如切片),将它们进行比 较就会失败并且panic:

var x interface{} = []int{1, 2, 3}
 fmt.Println(x == x) // panic: comparing uncomparable type []int

一个包含nil指针的接口不是nil接口

一个不包含任何值的nil接口值和一个刚好包含nil指针的接口值是不同的。这个细微区别产生了一个容 易绊倒每个Go程序员的陷阱。

总结

  1. 通过满足接口定义的方法,类型就可以成为此接口的类型
  2. 接口的实现依托于动态分配具体类型。编译器把代码生成在类型描述符的方法上。
  3. 接口值可以使用 ==、!=来进行比较。然而接口值如果动态类型是不可比较的话,那么进行比较会失败,并且panic(不建议使用)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容

  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,739评论 2 9
  • 本文来自“灰子学技术”,原文链接如下所示:https://mp.weixin.qq.com/s/ZBd1UcIJF...
    灰常出色阅读 583评论 0 6
  • 大家好,我是谢伟,是一名程序员。 下面的学习是一个系列,力求从初学者的角度学会go 语言,达到中级程序员水平。 这...
    谢小路阅读 1,911评论 0 6
  • 秋天到了,树叶们开始变美了。 金灿灿的银杏叶从树上飘落下来,地上就像铺了一层金色的地毯。 红艳艳的枫叶在空中向我们...
    秋天的丘阅读 537评论 0 51
  • 01 我给了自己半个小时平静的时间,做了个与时间赛跑的重要决定,然后骑上小黄蜂飞快地奔向第一个站点,那里是我战斗的...
    迷小希阅读 249评论 3 5