本文共 4266 字,大约阅读时间需要 14 分钟。
目录
接口是用来定义对象间交互的协议。
Duck type 就是鸭子类型,什么叫鸭子类型,也就是脚上有璞,身上有羽毛,嘴扁扁的, 虽然我们也不知道它是什么鸟,但是看起来像鸭子,我们就叫它鸭子。
type Programmer interface { WriteHelloWorld() string}
//定义接口的数据结构type GoProgrammer struct { Language string}//方法名和返回值都必须和接口定义的保持一致,//同时把这个方法绑定到 GoProgrammer 这个结构的指针上func (goProgrammer *GoProgrammer) WriteHelloWorld() string { return goProgrammer.Language + " print Hello World"}
package _interfaceimport "testing"//定义接口type Programmer interface { WriteHelloWorld() string}//定义接口的数据结构type GoProgrammer struct { Language string}//实例的方法名和返回值都必须和接口定义的保持一致,//同时把这个方法绑定到 GoProgrammer 这个结构的指针上func (goProgrammer *GoProgrammer) WriteHelloWorld() string { return goProgrammer.Language + " print Hello World"}//调用这个接口的实现func TestClient(t *testing.T) { goProgrammer := &GoProgrammer{Language: "Go"} res := goProgrammer.WriteHelloWorld() t.Log(res) //Go print Hello World}
结论:GoProgrammer 这个结构实现了 Programmer 这个接口 , 但是 Go 语言没有将显示的使用 implements 来进行依赖绑定, 而是使用了 duck type 的方式,只要方法名,参数和返回值是一样的 我们就认为这个实例就是 Programmer 接口的实现。
通过断言来将空接口转换为指定类型,而不是使用强制类型转换
//空接口转换为其它任何类型的格式//val 为转换后的结果值,当 ok==true 时,表示转换成功val, ok := empty_interface.(type)
package empty_interfaceimport ( "fmt" "testing")//空接口类型转换func ConvertEmptyInterface(p interface{}) { if val, ok := p.(int); ok { fmt.Printf("Empty interface convert to integer : %v\n", val) } else if val, ok := p.(string); ok { fmt.Printf("Empty interface convert to string : %v\n", val) } else if val, ok := p.([2]int); ok { fmt.Printf("Empty interface convert to array : %v\n", val) } else if val, ok := p.([]int); ok { fmt.Printf("Empty interface convert to slice : %v\n", val) } else if val, ok := p.(map[int]int); ok { fmt.Printf("Empty interface convert to map : %v\n", val) } else { fmt.Print("Unknow") }}//空接口可以转换为任何类型func TestEmptyInterfaceAssertion(t *testing.T) { number := 10 ConvertEmptyInterface(number) //Empty interface convert to integer : 10 str := "Go" ConvertEmptyInterface(str) //Empty interface convert to string : Go map1 := make(map[int]int, 10) ConvertEmptyInterface(map1) //Empty interface convert to map : map[] arr := [2]int{1, 2} ConvertEmptyInterface(arr) //Empty interface convert to array : [1 2] slice1 := make([]int, 3, 5) ConvertEmptyInterface(slice1) //Empty interface convert to slice : [0 0 0]}
package empty_interfaceimport ( "fmt" "testing")//空接口类型转换func ConvertEmptyInterface(p interface{}) { // p.(type)这种写法只能用于 switch 中 switch val:= p.(type) { case int: fmt.Printf("Empty interface convert to integer : %v\n", val) case string: fmt.Printf("Empty interface convert to string : %v\n", val) case [2]int: fmt.Printf("Empty interface convert to array : %v\n", val) case []int: fmt.Printf("Empty interface convert to slice : %v\n", val) case map[int]int: fmt.Printf("Empty interface convert to map : %v\n", val) default: fmt.Print("Unknow") }}//空接口可以转换为任何类型func TestEmptyInterfaceAssertion(t *testing.T) { number := 10 ConvertEmptyInterface(number) //Empty interface convert to integer : 10 str := "Go" ConvertEmptyInterface(str) //Empty interface convert to string : Go arr := [2]int{1, 2} ConvertEmptyInterface(arr) //Empty interface convert to array : [1 2] slice1 := make([]int, 3, 5) ConvertEmptyInterface(slice1) //Empty interface convert to slice : [0 0 0] map1 := make(map[int]int, 10) ConvertEmptyInterface(map1) //Empty interface convert to map : map[]}
为何写这种两段式的switch语句会报错呢 (use of .(type) outside type switch)?
对于这个情况,后面的 val 有什么用呢?前面 val 已经被赋值并且可以在下面使用了。 val 的值是
类型,你可以通过 %T 来输出。
//空接口类型转换func ConvertEmptyInterface(p interface{}) { switch val := p.(type); val { //code }}
更小的接口,让接口的负担更轻,接口的复用性更高,在Go里面有很多 Single method (即只有一个方法的接口),例如像下面这样:
type Reader interface { Read (p []byte) (num int)}type Writer interface { Write (p []byte) (num int)}
type ReaderWriter interface { Reader Writer}
//例如我这个方法只需要用到了 Reader,就只依赖 Reader 接口,//没必要依赖 ReaderWriter 接口func GetAllReaders(reader Reader) error { //code return nil}
当我们定义了较小的接口后,为了发挥小接口的优势,我们使用的方法一定要尽量依赖它最小的接口,这样接口中的方法才能被更多的地方去复用。
注:这篇博文是我学习中的总结,如有转载请注明出处:
上一篇:
下一篇: