golang interface

在golang中interface表示两种意思

  • 一组方法的集合
  • 一种数据类型

一组方法的集合(抽象数据类型)

和Java里用法类似。实现了这些方法的类型都可以作为参数类型为这个接口的参数值。

一种数据类型(interface{})

一种任何数据类型都可以作为它的值的类型。

为何使用接口

  • 编写通用算法
1
2
3
4
5
6
7
8
9
10
// 从Reader里读取数据,reader可能是文件,网络,内存等
func readFrom(rd io.Reader) ([]byte, error) {
var bs = make([]byte, 1024)
_, err := rs.Read(bs)
if err != nil {
return nil, err
}

return bs, nil
}
  • 编写易于测试的代码
    项目里依赖别的库,别的服务;需要将这些库和依赖抽象为接口。好在测试的时候mock掉,替换为单元测试环境下的假设的实现。

  • 解耦不同组件,让他们通过接口通信。
    不依赖具体实现,只依赖接口;当实现变化的时候,不用改变代码。

常用操作

  • type assertion
1
2
3
4
5
var v interface{} = 100
intVal, ok := v.(int) // ok: true, intVal: int

v = "sss"
strVal, ok := v.(string) // ok: true, strVal: "sss"
  • type switch
1
2
3
4
5
6
7
8
9
10
11
12
func typeSwitch(v interface{}) {
switch t := v.(type) {
case string:
fmt.Printf("%s\n", t)
case int,int64,int32:
fmt.Printf("%d\n", t)
case float32, float64:
fmt.Printf("%f\n", t)
default:
fmt.Printf("unknown type: %v\n", t)
}
}
  • 接口组合
1
2
3
4
5
6
7
8
9
10
11
12
type MoneyMaker interface {
MakeMoney() int64
}

type MoneySpender interface {
SpendMoney() int64
}

type MoneyMakeSpender interface {
MoneyMaker
MoneySpender
}