Loading... ### 什么是空接口? 空接口是特殊形式的接口类型,普通的接口都有方法,而空接口没有定义任何方法,也因此,我们可以说所有类型都至少实现了空接口。 ```go type empty_iface interface { } ``` 每一个接口都包含两个属性,一个是值,一个是类型。 而对于空接口来说,这两者都是nil,可以用fmt来验证一下。 ```go package main import "fmt" func main() { var i interface{} fmt.Printf("type:T%,value:v%",i,i) } ``` 输出如下: ```shell type: <nil>,value:<nil> ``` --- ### 如何使用空接口? 1. 通常我们会直接用`interface{}`作为类型声明一个实例,而这个实例可以承载任何类型的值。 ```go package main import "fmt" func main() { // 声明一个空接口实例 var i interface{} // 存int没有问题 i = 1 fmt.Println(i) // 存字符串没有问题 i = "hello" fmt.Println(i) // 存布尔值没有问题 i = true fmt.Println(i) } ``` 2. 如果想让你的函数可以接收任意类型的值,也可以使用空接口 接收`一个任意类型`的值 示例 ```go package main import "fmt" func myfunc(iface interface{}) { fmt.Println(iface) } func main() { a := 10 b := "hello" c := true myfunc(a) myfunc(b) myfunc(c) } ``` 接收`任意个任意类型`的值 示例 ```go package main import "fmt" func myfunc(ifaces ...interface{}) { for _,iface := range ifaces { fmt.Println(iface) } } func main() { a := 10 b := "hellow" c := true myfunc(a,b,c) } ``` 3. 你也可以定义一个可以接收任意类型的array、slice、map、struct,例如这边定义一个切片 ```go package main import "fmt" func main() { any := make([]interface{},5) any[0] = 11 any[1] = "hello world" any[2] = []int{11,22,33} for _,value := range any { fmt.Println(value) } } ``` ### 空接口几个要注意的坑 1. 空接口可以承载任意值,但并不代表任意类型就可以承接空接口类型的值 从实现的角度看,任何类型的值都满足空接口。因此空接口类型可以保存任何值,也可以从空接口中取出原值。 但要是把一个空接口类型的对象,再赋值给一个固定类型(比如int,string等类型)的对象赋值,是会报错的。 ```go package main func main() { // 声明变量a,类型int,初始值为1 var a int = 1 // 声明i变量,类型为interface,初始值为a,此时i的值变为1 var i interface{} = a // 声明b变量,尝试赋值i var b int = i } ``` Go里直接禁止了这种反向操作。报错如下: ```shell ./main.go:16:6: cannot use i (type interface {}) as type int in assignment: need type assertion ``` 2. 当空接口承载数组和切片后,该对象无法再进行切片 ```go package main import "fmt" func main() { sli := []int{2,3,5,7,11,13} var i interface{} i = sli g := i[1:3] fmt.Println(g) } ``` 执行会报错 ```shell ./main.go:16:8: cannot slice i (type interface {}) ``` 3. 当使用空接口来接收任意类型的参数时,它的静态类型时interface{},但动态类型是(int,string还是其他类型)我们并不知道,因此需要使用类型断言。 ```go package main import "fmt" func myfunc(i interface{}) { switch i.(type) { case int: fmt.Println("参数类型是 int") case string: fmt.Println("参数类型是 string") } } func main() { a := 10 b := "hello" myfunc(a) myfunc(b) } ``` 输出如下 ```shell 参数类型是 int 参数类型是 string ``` 最后修改:2021 年 03 月 16 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 感谢赏赐的coffee~