后端基础Day3 Golang的接口 | 青训营笔记

69 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

接口在Go语言有着至关重要的地位。如果说goroutine和channel 是支撑起Go语言的并发模型 的基石,让Go语言在如今集群化与多核化的时代成为一道极为亮丽的风景,那么接口是Go语言 整个类型系统的基石,让Go语言在基础编程哲学的探索上达到前所未有的高度。

Java的接口

interface IFoo {
void Bar();
}
class Foo implements IFoo { // Java文法
// ...
}

这种接口(包括C++的)与其接口实现类的对应关系是由包路径和声明(implements) 决定的, 我们称之为"侵入式接口"

非侵入式接口

在Go语言中,一个类只需要实现了接口要求的所有函数,我们就说这个类实现了该接口

非侵入式接口的优点:

其一,Go语言的标准库,再也不需要绘制类库的继承树图

其二,实现类的时候,只需要关心自己应该提供哪些方法,不用再纠结接口需要拆得多细才合理。接口由使用方按需定义,而不用事前规划。

其三,不用为了实现一个接口而导入一个包,因为多引用一个外部的包,就意味着更多的耦合。接口由使用方按自身需求来定义,使用方无需关心是否有其他模块定义过类似的接口。

接口语法

接口赋值

  • 将对象实例赋值给接口:
type Integer intfunc (a Integer) Less(b Integer) bool {
    return a < b
}
​
func (a *Integer) Add(b Integer) {
    *a += b
}
​
type LessAdd interface {
    Less(b Integer) bool
    Add(b Integer)
}

如果定义如上方法和接口, 然后将Integer实例赋值给LessAdd接口: 则必须用&取地址后赋值, 我的理解是必须拿到a的地址, 才可以用Add方法去修改a的值, 否则Integer未实现接口的Add方法

对于这个问题, 该某乎答主的解释是: 在类型的接收者不包含指针类型时, 可以使用a或者&a, 使用&a时编译器进行解引用

如何理解Golang中的接口? - 知乎 (zhihu.com)

var a Integer = 1
var i LessAdd = a   //编译器报错
var i LessAdd = &a
  • 接口间赋值

AB接口存在子集关系, 则大的可以赋值给小的(不影响调用小的方法)

接口查询

  • 查询接口是否实现了另一个接口:
var file1 Writer = ...
if file5, ok := file1.(two.IStream); ok {
    //...
}
  • 接口指向的对象是否是某个类型
var file1 Writer = ...
if file6, ok := file1.(*File); ok {
    //...
}
  • 类型查询, 用xx.(type)即可获得对象类型
var v1 interface{} = ...
    switch v := v1.(type) {
    case int: // 现在v的类型是int
    case string: // 现在v的类型是string
    ...
}