概述
interface 是一个定义了方法签名的集合,用来指定对象的行为,如果对象做到了Interfac中方法集定义的行为,那就可以说实现了Interface。
声明
接口的声明使用 interface 关键字 。
接口按照约定只包含一个方法的,接口的名字由方法名加 [e]r 后缀组成,例如 Printer、Reader、Writer、Logger、Converter 等等。还有一些不常用的方式(当后缀 er 不合适时),比如 Recoverable,此时接口名以 able 结尾,或者以 I 开头(像 .NET 或 Java 中那样)。
- 只要某个类型拥有该接口的所有方法签名,即算实现该接口,无需显示声明实现了哪个接口。
- 接口只有方法声明,没有实现,没有数据字段。
- 接口可以匿名嵌入其他接口,或嵌入结构中。
/* define an interface */type interface_name interface {method_name1 [return_type]method_name2 [return_type]method_name3 [return_type]...method_namen [return_type]}/* define a struct */type struct_name struct {/* variables */}/* implement interface methods*/func (struct_name_variable struct_name) method_name1() [return_type] {/* method implementation */}...func (struct_name_variable struct_name) method_namen() [return_type] {/* method implementation */}
空接口
没有任何方法的接口,我们称之为空接口。所以任何类型都实现了空接口,空接口表示为:
interface {}
空接口用途
1 GO语言没有泛型,如果一个函数需要接收任意类型的参数, 则参数类型可以使用空接口类型,这是弥补没有泛型的一种手段。
空接口和反射
空接口是反射实现的基础 ,反射库就是将相关具体的类型转换并赋值给空接口后才去处理。
空接口和nil
空接口有两个字段, 一个是实例类型,另 一个是指向绑定实例的指针,只有两个都为nil时 ,空接口才为nil。
指针接收和值接收
TypeAssertion
判断接口变量的的具体类型,需要使用到类型断言type assertion。它的语法是:
变量名称.(数据类型)
判断当前的a的数据类型是字符串,如果当前a不是字符串使用下面写法会引起panic
func printStr(a interface{}){fmt.Println(a.(string))}func main() {a := 10printStr(a)}
为了避免 panic 错误发生,可以通过如下操作来进行断言检查,断言会返回一个bool类型的参数 告诉是否断言的类型是否真的匹配
t, ok := i.(T)
断言成功,ok 的值为 true,断言失败 t 值为T类型的默认值,也不会引起panic。如下
func printStr(a interface{}){if v, ok := a.(string); ok {fmt.Println(v)}else {fmt.Println("不是字符 无法打印")}}func main() {a := 10printStr(a)printStr("test")}
TypeSwitch
另外一种判断interface变量的具体类型,那就是利用 switch 语句。
func printValue(v interface{}) {switch v := v.(type) {case string:fmt.Printf("%v is a string\n", v)case int:fmt.Printf("%v is an int\n", v)default:fmt.Printf("The type of v is unknown\n")}}func main() {v := 10printValue(v)s := "test"printValue(s)}
编译期间判断是否实现了某个接口
var _ Pooler = new(WeightedRoundRobin)
Pooler是一个接口类型。
type Pooler interface {// ...}
如果说次接口没有被实现,ide会有红横线出现,另一方面在编译的时候会出现报错。两方面的提示来保证写底层代码的接口是有被实现的。
接口类型&nil
package mainimport "fmt"type Foo interface {bar()}type FooType struct {}func (f FooType)bar(){fmt.Println("hello world")}func main() {var f Foofmt.Println(f==nil)fmt.Printf("%T %v\n",f,f)var t *FooTypefmt.Println(t==nil)fmt.Printf("%T %v\n",t,t)f = tfmt.Println(f==nil)fmt.Printf("%T %v\n",f,f)}
打印结果
true<nil> <nil>true*main.FooType <nil>false*main.FooType <nil>
自动检测类型是否实现接口
package maintype Foo interface {bar()}type FooType struct {}//func (f FooType)bar(){// fmt.Println("hello world")//}func main() {var _ Foo = (*FooType)(nil)}
参考
https://blog.csdn.net/tomatomas/article/details/95880842
https://blog.keyboardman.me/2018/05/12/nil-in-go/
https://www.jianshu.com/p/dd80f6be7969
