11.1 接口

定义接口

type Namer interface {
    Method1(param_list) return_type
    Method2(param_list) return_type
    ...
}

接口是一个函数原型的集合,规定了要实现的功能。

命名规范

接口的名字由方法名加 [e] r 后缀组成,例如 PrinterReaderWriterLoggerConverter 等等。还有一些不常用的方式(当后缀 er 不合适时),比如 Recoverable,此时接口名以 able 结尾,或者以 I 开头(像 .NETJava 中那样)。

11.2 反射

类型断言

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

varI 是接口变量。

如果转换合法,vvarI 转换到类型 T 的值,ok 会是 true;否则 v 是类型 T 的零值,okfalse,也没有运行时错误发生。

类型判断:type-switch

switch t := areaIntf.(type) {
case *Square:
	fmt.Printf("Type Square %T with value %v\n", t, t)
case *Circle:
	fmt.Printf("Type Circle %T with value %v\n", t, t)
case nil:
	fmt.Printf("nil value: nothing to check?\n")
default:
	fmt.Printf("Unexpected type %T\n", t)
}

t 可省略。

判断接口是否实现

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

空接口

type Any interface {}

空接口类型可以随意赋值。Go 的败笔

反射包

func TypeOf(i interface{}) Type
func ValueOf(i interface{}) Value

接口与动态类型

Go 中的类型只要实现了某接口的所有方法,就隐式地实现了该类型。

type IDuck interface {
	Quack()
	Walk()
}

func DuckDance(duck IDuck) {
	for i := 1; i <= 3; i++ {
		duck.Quack()
		duck.Walk()
	}
}

type Bird struct {
	// ...
}

func (b *Bird) Quack() {
	fmt.Println("I am quacking!")
}

func (b *Bird) Walk()  {
	fmt.Println("I am walking!")
}

func main() {
	b := new(Bird)
	DuckDance(b)
}

11.3 反射深入

当我们想要让编码过程更加自动化,就不可避免地要使用反射了。

reflect.Type 和 reflect.Value

Type

Type 接口描述了与类型相关的信息:

type Type interface {
	Align () int // 字节对齐位置    
	FieldAlign () int // 字节在结构体的对其位置    
	Method (n int) Method // 类型的第 n 个方法
	MethodByName (string) (Method, bool) // 通过方法名获取类型的方法
	NumMethod () int // 方法数
	Name () string // 类型名
	PkgPath () string // 包路径
	Size () uintptr // 占用的空间大小
	String () string // 字符串表示
	Kind () Kind // 就是数据类型,比如 uint8, Interface 这样
	Implements (u Type) bool // 判断是否实现了某个类型
	AssignableTo (u Type) bool // 判断是否可赋给某类型
	ConvertibleTo (u Type) bool // 判断是否可转换到某类型
	Comparable () bool // 判断该类型是否可比较大小
	Bits () int // 类型的比特数	
	ChanDir () ChanDir // 通道方向,即收、发、可收可发
	IsVariadic () bool // 最后一个参数是否是可变参数 ...
	Elem () Type // 获取此类型对应的基本数据类型(Array, Chan, Map, Ptr, or Slice)不是则引发 panic
    Field (i int) StructField // 返回结构体的第 i 个字段

	// FieldByIndex returns the nested field corresponding
	// to the index sequence. It is equivalent to calling Field
	// successively for each index i.
	// It panics if the type's Kind is not Struct.
    // 返回嵌套的字段
	FieldByIndex(index []int) StructField

	// 返回 name 对应的字段
	FieldByName(name string) (StructField, bool)

	// 返回第一个匹配函数(能使函数返回 true)的字段
	FieldByNameFunc(match func(string) bool) (StructField, bool)
	// 返回函数第 i 个入参的类型
	In(i int) Type
	// 返回字典的 key 的类型
	Key() Type
	// 返回数组的长度
	Len() int
	// 返回结构体的字段数量
	NumField() int
    // 返回入参的数量
	NumIn() int
	// 返回出参的数量
	NumOut() int
	// 返回出参的类型
	Out(i int) Type

	common() *rtype
	uncommon() *uncommonType
}

reflect.rtypereflect.Type 接口的实现。

Value

Value 接口是一个 Go 值类型的反射接口,下面简称值类型Value 零值,表示不持有任何值。持有零值,说明 Value 肯定不是零值。

type Value struct {
	// 表示此值的类型
	typ *rtype
	// 如果值是指针,则 ptr 指向指针的目标
	ptr unsafe.Pointer
	//flag 存有此值的元数据,最低位标志表名此值是:
    // 					通过未导出、未封装的字段取得的(只读)
	//	- flagStickyRO: obtained via unexported not embedded field, so read-only
	//	- flagEmbedRO: 通过未导出、封装的字段取得的(只读)
	//	- flagIndir: 一个指针
	//	- flagAddr: v.CanAddr is true (implies flagIndir) 即可被取地址
	//	- flagMethod: v 是一个方法
    // 之后 5 位表示值的类型
	flag
	// 对于一个方法值,它表示一个柯里化(https://zh.wikipedia.org/zh/%E6%9F%AF%E9%87%8C%E5%8C%96 其实就是把多参数的函数变成单参数函数的连续调用)的方法调用
	// like r.Read for some receiver r. The typ+val+flag bits describe
	// the receiver r, but the flag's Kind bits say Func (methods are
	// functions), and the top bits of the flag give the method number
	// in r's type's method table.
}

value 的函数很多,大概有三千行。签名如下:


// 获取某值的值类型
func ValueOf(i interface{}) Value
// 返回一个持有零值的 Type 类型的,值类型
func Zero(typ Type) Value
// 创建一个 [指向类型为 Type 的] 指针,指针指向零值的 Type 类型实例
func New(typ Type) Value
// 和上面一样,不过利用的是现有的指针
func NewAt(typ Type, p unsafe.Pointer) Value
// 
func Indirect(v Value) Value
func MakeSlice(typ Type, len, cap int) Value
func MakeMap(typ Type) Value
func MakeChan(typ Type, buffer int) Value
func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value
func Append(s Value, x ...Value) Value
func AppendSlice(s, t Value) Value
func (v Value) IsValid() bool
func (v Value) IsNil() bool
func (v Value) Kind() Kind
func (v Value) Type() Type
func (v Value) Convert(t Type) Value
func (v Value) Elem() Value
func (v Value) Bool() bool
func (v Value) Int() int64
func (v Value) OverflowInt(x int64) bool
func (v Value) Uint() uint64
func (v Value) OverflowUint(x uint64) bool
func (v Value) Float() float64
func (v Value) OverflowFloat(x float64) bool
func (v Value) Complex() complex128
func (v Value) OverflowComplex(x complex128) bool
func (v Value) Bytes() []byte
func (v Value) String() string
func (v Value) Pointer() uintptr
func (v Value) InterfaceData() [2]uintptr
func (v Value) Slice(i, j int) Value
func (v Value) Slice3(i, j, k int) Value
func (v Value) Cap() int
func (v Value) Len() int
func (v Value) Index(i int) Value
func (v Value) MapIndex(key Value) Value
func (v Value) MapKeys() []Value
func (v Value) NumField() int
func (v Value) Field(i int) Value
func (v Value) FieldByIndex(index []int) Value
func (v Value) FieldByName(name string) Value
func (v Value) FieldByNameFunc(match func(string) bool) Value
func (v Value) Recv() (x Value, ok bool)
func (v Value) TryRecv() (x Value, ok bool)
func (v Value) Send(x Value)
func (v Value) TrySend(x Value) bool
func (v Value) Close()
func (v Value) Call(in []Value) []Value
func (v Value) CallSlice(in []Value) []Value
func (v Value) NumMethod() int
func (v Value) Method(i int) Value
func (v Value) MethodByName(name string) Value
func (v Value) CanAddr() bool
func (v Value) Addr() Value
func (v Value) UnsafeAddr() uintptr
func (v Value) CanInterface() bool
func (v Value) Interface() (i interface{})
func (v Value) CanSet() bool
func (v Value) SetBool(x bool)
func (v Value) SetInt(x int64)
func (v Value) SetUint(x uint64)
func (v Value) SetFloat(x float64)
func (v Value) SetComplex(x complex128)
func (v Value) SetBytes(x []byte)
func (v Value) SetString(x string)
func (v Value) SetPointer(x unsafe.Pointer)
func (v Value) SetCap(n int)
func (v Value) SetLen(n int)
func (v Value) SetMapIndex(key, val Value)
func (v Value) Set(x Value)
func Copy(dst, src Value) int
func DeepEqual(a1, a2 interface{}) bool