Contents

golang-学习笔记-接口(Interfaces)与反射(reflection)

go官方文档 go语言参考

在写过很多go代码之后,感觉自己并没有完全掌握go语言,还有很多知识盲区,所以有了这个go学习笔记系列,本系列是作者跟着电子书重新复习go语言相关内容的笔记

接口是什么

1
2
3
4
5
type Namer interface {
    Method1(param_list) return_type
    Method2(param_list) return_type
    ...
}

实现接口:定义与接口内部函数签名字段相同的方法。

类型不需要显式声明它实现了某个接口:接口被隐式地实现。多个类型可以实现同一个接口。

实现某个接口的类型(除了实现接口方法外)可以有其他的方法。

一个类型可以实现多个接口。

接口类型可以是一个实例的引用, 该实例的类型实现了此接口(接口是动态类型)。

接口嵌套接口

一个接口可以包含一个或多个其他的接口,这相当于直接将这些内嵌接口的方法列举在外层接口中一样。

类型断言:如何检测和转换接口变量的类型

1
2
3
4
5
if v, ok := varI.(T); ok {  // checked type assertion
    Process(v)
    return
}
// varI is not of type T

varI 必须是一个接口变量,当转换不成功时会给v是T类型的零值,ok为false

类型判断:type-switch

1
2
3
4
5
6
7
8
9
switch areaIntf.(type) {
case *Square:
    // TODO
case *Circle:
    // TODO
...
default:
    // TODO
}

这里的switch不能使用fallthrough

测试一个值是否实现了某个接口

1
2
3
4
5
6
7
type Stringer interface {
    String() string
}

if sv, ok := v.(Stringer); ok {
    fmt.Printf("v implements String(): %s\n", sv.String()) // note: sv, not v
}

使用接口使代码更具有普适性。

使用方法集与接口

记住3点即可

  1. go语言里面只有值传递,包括方法接收者
  2. T类型的方法集为T的方法,*T类型的方法集为T和 *T的方法
  3. go语言有隐式取解引用,即.运算符可以直接作用于指针,编译器会自动转换为*p.xxx或者p.xxx

第一个例子:使用 Sorter 接口排序

实现Len(),Less(i, j)和Swap(i, j)可以直接调用sort.Sort(data Interface)

第二个例子:读和写

1
2
3
4
5
6
7
type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

io 包里的 Readers 和 Writers 都是不带缓冲的。bufio 包里提供了对应的带缓冲的操作。

空接口

概念

1
type Any interface {}

每个 interface {} 变量在内存中占据两个字长:一个用来存储它包含的类型,另一个用来存储它包含的数据或者指向数据的指针

构建通用类型或包含不同类型变量的数组

1
2
3
4
5
type Element interface{}

type Vector struct {
    a []Element
}

复制数据切片至空接口切片

1
2
3
4
5
var dataSlice []myType = FuncReturnSlice()
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
for i, d := range dataSlice {
    interfaceSlice[i] = d
}

接口到接口

一个接口的值可以赋值给另一个接口变量,只要底层类型实现了必要的方法

 |