go interface
2022-03-28 本文已影响0人
hehehehe
1、空接口
- 空接口是特殊形式的接口类型,普通的接口都有方法,而空接口没有定义任何方法口,也因此,我们可以说所有类型都至少实现了空接口。
- type empty_iface interface {
} - 每一个接口都包含两个属性,一个是值,一个是类型
- 对于空接口来说,这两者都是 nil
func main() {
var i interface{}
fmt.Printf("type: %T, value: %v", i, i)
}
type: <nil>, value: <nil>
- 空接口可以承载任意值,但不代表任意类型就可以承接空接口类型的值
- 当空接口承载数组和切片后,该对象无法再进行切片
- 当你使用空接口来接收任意类型的参数时,它的静态类型是 interface{},但动态类型(是 int,string 还是其他类型)我们并不知道,因此需要使用类型断言。
静态类型和动态类型
静态类型(static type)是变量声明的时候的声明类型,在变量声明、new方法创建对象时或者结构体(struct)的元素的类型定义,参数类型等。
接口(interface)类型的变量还有一个动态类型,它是运行时赋值给这个变量的具体的值的类型(当然值为nil的时候没有动态类型)。一个变量的动态类型在运行时可能改变,
这主要依赖它的赋值。
var x interface{} // x 为零值 nil,静态类型为 interface{}
var v *T // v 为零值 nil, 静态类型为 *T
x = 42 // x 的值为 42,动态类型为int, 静态类型为interface{}
x = v // x 的值为 (*T)(nil), 动态类型为 *T, 静态类型为 *T
2、接口的三个规则
-
调用函数时的隐式转换
import (
"fmt"
)
func printType(i interface{}) {
switch i.(type) {
case int:
fmt.Println("参数的类型是 int")
case string:
fmt.Println("参数的类型是 string")
}
}
func main() {
a := 10
printType(a)
}
使用这种写法时,Go 会默默地为我们做一件事,就是把传入函数的参数值(注意:Go 语言中的函数调用都是值传递的)的类型隐式的转换成 interface{} 类型
-
如何进行接口类型的显示转换
难道我使用类型断言,只能通过一个接收空接口类型的函数才能实现吗?
var a int = 25
b := interface{}(a)
*interface{}
func Aaa(str *interface{}) {
fmt.Println(*str)
}
var cc = "aaa"
dd :=interface{}(cc)
Aaa(&dd)
func main() {
a := 10
switch interface{}(a).(type) {
case int:
fmt.Println("参数的类型是 int")
case string:
fmt.Println("参数的类型是 string")
}
}
-
类型断言中的隐式转换
当类型断言完成后,会返回一个静态类型为你断言的类型的对象,也就是说,当我们使用了类型断言,Go 实际上又会默认为我们进行了一次隐式的类型转换
3、类型断言
- 检查 i 是否为 nil
- 检查 i 存储的值是否为某个类型
t, ok:= i.(T)
断言一个接口对象(i)里不是 nil,并且接口对象(i)存储的值的类型是 T,
如果断言成功,就会返回其值给 t,并且此时 ok 的值 为 true,表示断言成功
Type Switch
func findType(i interface{}) {
switch x := i.(type) {
case int:
fmt.Println(x, "is int")
case string:
fmt.Println(x, "is string")
case nil:
fmt.Println(x, "is nil")
default:
fmt.Println(x, "not type matched")
}
}
func main() {
findType(10) // int
findType("hello") // string
var k interface{} // nil
findType(k)
findType(10.23) //float64
}
10 is int
hello is string
<nil> is nil
10.23 not type matched
如果你的值是 nil,那么匹配的是 case nil
如果你的值在 switch-case 里并没有匹配对应的类型,那么走的是 default 分支
- 类型断言,仅能对静态类型为空接口(interface{})的对象进行断言,否则会抛出错误,具体内容可以参考:关于接口的三个”潜规则”
- 类型断言完成后,实际上会返回静态类型为你断言的类型的对象,而要清楚原来的静态类型为空接口类型(interface{}),这是 Go 的隐式转换。