一个例子短平快的了解 interface 的语法
-
接口定义
-
接口实现
-
接口零值 nil
-
表达式实现接口的方法,可以赋值给接口变量
- 实例赋值给接口
- 指针赋值给接口
- 接口赋值给接口
-
T 型值方法集 (t T)
-
*T 型值方法集 (t T) 和 (t *T)
-
判等,可赋值,可判等
-
类型断言 t = x.(T)
- 断言是具体类型
- 断言是接口类型
- 断言失败,崩溃
- 断言空接口值,肯定失败,崩溃
- 断言返回二元组,如果成功返回值 和 true
- 断言返回二元组,如果失败返回 nil 和 false, 而不是崩溃
-
类型分支
例子
package main
import "fmt"
//接口定义
type Reader interface {
Read() T
}
//
type Writer interface {
Write(arg T)
}
//
type ReadWrite interface {
Read() T
Write(arg T)
}
// 接口实现
type T int64
func (t T) Read() T {
return t
}
func (t *T) Write(arg T) {
*t = arg
}
func main() {
var t T = 123
var r Reader
var w Writer
var rw ReadWrite
var n ReadWrite
//接口零值nil
fmt.Println(t, r, w, rw, n) //123 <nil> <nil> <nil> <nil>
//表达式实现接口的方法,可以赋值给接口变量
r = t //实例赋值给接口
rw = &t //指针赋值给接口
w = rw //接口赋值给接口
// T 型值方法集 (t T) ,这里 Read
r = t
//w = t //(t *T) 型方法不是 T 型值的方法集
//T(10).Write(t) //(t *T) 型方法不是 T 型值的方法集 <== T(10) 无法取地址,无法调用 Write 方法
// *T 型值方法集 (t T) 和 (t *T), 这里 Read Write
r = &t
w = &t
//判等,可赋值,可判等
fmt.Println(t == r, &t == w, &t == rw) // false true true
//类型断言 t = x.(T)
r = t
t = r.(T) //断言是具体类型
r = r.(Reader) //断言是接口类型
// w = r.(Writer) //断言失败,崩溃
// rw = n.(ReadWrite) //断言空接口值,肯定失败,崩溃
r, ok := r.(Reader) //断言返回二元组,如果成功返回值 和 true
fmt.Println(r, ok) //123 true
w, ok = r.(Writer) //断言返回二元组,如果失败返回 nil 和 false, 而不是崩溃
fmt.Println(w, ok) //<nil> fals
//类型分支
switch rw := rw.(type) { //左边 rw 是新建的和右边 rw 同名的变量
case nil: //rw == nil 时
case Writer:
// fallthrough //不能用 fallthrough
case Reader:
case ReadWrite:
default: //以上都不满足时 default
fmt.Sprintf("%T:%v", rw, rw)
}
}
输出
123 <nil> <nil> <nil> <nil>
false true true
123 true
<nil> false
从源码分析接口类型
//GOPATH\src\runtime\runtime2.go
type iface struct {
tab *itab
data unsafe.Pointer
}
type eface struct {
_type *_type
data unsafe.Pointer
}
// layout of Itab known to compilers
// allocated in non-garbage-collected memory
// Needs to be in sync with
// ../cmd/compile/internal/gc/reflect.go:/^func.dumptypestructs.
type itab struct {
inter *interfacetype
_type *_type
hash uint32 // copy of _type.hash. Used for type switches.
_ [4]byte
fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}
//GOPATH\src\runtime\type.go
// Needs to be in sync with ../cmd/link/internal/ld/decodesym.go:/^func.commonsize,
// ../cmd/compile/internal/gc/reflect.go:/^func.dcommontype and
// ../reflect/type.go:/^type.rtype.
type _type struct {
size uintptr
ptrdata uintptr // size of memory prefix holding all pointers
hash uint32
tflag tflag
align uint8
fieldalign uint8
kind uint8
alg *typeAlg
// gcdata stores the GC type data for the garbage collector.
// If the KindGCProg bit is set in kind, gcdata is a GC program.
// Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
gcdata *byte
str nameOff
ptrToThis typeOff
}
go 类型分类
- 具体类型 int,string,struct{},…
- 抽象类型 interface
interface接口类型,无数据和方法,定义了一个方法集(一个多个方法声明,包含方法名和签名).不可以实例化,可以定义一个变量.
接口类型
- itab
- 接口类型描述符(静态类型 inter)
- 具体类型描述符(动态类型 _type)
- 方法集(fun)
- 具体类型值(动态值 data)
空接口类型
- 具体类型描述符(动态类型 _type)
- 具体类型值(动态值 data)