2.08 Go之空接口类型(interface{})


2.08 Go之空接口类型(interface{})

空接口的特点

可以保存任何值,也可以从空接口中取出原值。

空接口的内部实现保存了对象的类型和指针。使用空接口保存一个数据的过程会比直接用数据对应类型的变量保存稍慢。

将值保存到空接口

package main
?
import "fmt"
?
func main() {
   // 声明一个空接口
   var any interface{}
?
   // 给空接口赋值
   any = 1
   // 提供给 fmt.Println 的类型依然是 interface{}
   fmt.Println(any)
?
   // 为 any 赋值一个字符串 hello。此时 any 内部保存了一个字符串。但类型依然是 interface{}
   any = "hello"
   fmt.Println(any)
?
   any = false
   fmt.Println(any)
}

注意:

保存到空接口的值不能直接按照类型取值,会报错。但是可以根据断言类型去取值

从空接口获取值

package main
?
import "fmt"
?
func main() {
   // 声明一个int类型的变量
   var a int = 1
?
   // 声明一个接口,将i赋值给接口
   var i interface{} = a
?
   // 声明变量b然后直接赋值--->编译不通过
   /*
   将 a 的值赋值给 i 时,虽然 i 在赋值完成后的内部值为 int,但 i 还是一个 interface{} 类型的变量
    */
   //var b int = i
?
   // 声明变量b通过类型断言赋值--->编译通过
   var b int = i.(int)
   fmt.Println(b)
}

空接口的值比较

特点:

空接口在保存不同的值以后可以和其他变量一样使用==进行比较

  • 类型不同的空接口间比较结果不相同--->Go语言会优先比较值的类型

func main() {
   // 声明一个接口,保存整型数据
   var a interface{} = 100
   
   // 声明一个接口,保存字符串类型数据
   var b interface{} = "hi"
   
   // 比较这两个接口--->输出false
   fmt.Println(a == b)
}
  • 不能比较空接口中的动态值

当接口中保存有动态类型的值时,运行时将触发错误:

func main() {
   // c保存包含10的整型切片
   var c interface{} = []int{10}
   
   // d保存包含20的整型切片
   var d interface{} = []int{20}
   
   // 这里会发生崩溃
   fmt.Println(c == d)
}

类型的可比较性

类 型说 明
map 宕机错误,不可比较
切片([]T) 宕机错误,不可比较
通道(channel) 可比较,必须由同一个 make 生成,也就是同一个通道才会是 true,否则为 false
数组([容量]T) 可比较,编译期知道两个数组是否一致
结构体 可比较,可以逐个比较结构体的值
函数 可比较