类型断言
作用:用于提取一个接口底层值。
语法:i.(T), 用来获取混合类型是T的接口的底层值,让我们来看一下例子:
package main
import (
"fmt"
)
func assert(i interface{}) {
s := i.(int) //get the underlying int value from i
fmt.Println(s)
}
func main() {
var s interface{} = 56
assert(s)
}
上面的例子中,我们定义了一个空接口类型的变量s,然后给他赋值了整数类型值56,此时,s为混合类型,即空接口类型和整数类型,然后我们可以通过类型断言来获取整数类型的具体值,即56。
正常情况下程序可以正常运行,并且得到我们想要的值,但是如果是下面这种情况的话,结果就不会按照我们预期的来了。还是看一个例子:
package main
import (
"fmt"
)
func assert(i interface{}) {
s := i.(int)
fmt.Println(s)
}
func main() {
var s interface{} = "Steven Paul"
assert(s)
}
上面的例子中,我们给空接口赋值了字符串,因此此时的混合类型是空接口和字符串类型,而我们在这里断言的是整数类型,因此产生一个panic,
panic: interface conversion: interface {} is string, not int.
为了解决这个问题,我们可以使用以下语法:
v, ok := i.(T)
如果i的混合类型是T,那么v的值是i的底层值,且ok的值为true。
如果i的混合类型不是T,那么v的值是类型T的零值,且ok的值为false, 而且程序不会panic。
package main
import (
"fmt"
)
func assert(i interface{}) {
v, ok := i.(int)
fmt.Println(v, ok)
}
func main() {
var s interface{} = 56
assert(s)
var i interface{} = "Steven Paul"
assert(i)
}
输出结果
56 true
0 false
类型切换
类型切换用于将接口的具体类型与各种case语句中指定的多种类型进行比较。它类似于switch case。唯一的区别是case指定类型而不是值,而不是常规switch中的情况。
类型切换的语法类似于类型断言。在用于类型断言的语法i.(T)中,应将类型T替换为用于类型切换的关键字type。让我们在下面的程序中查看其工作方式。
package main
import (
"fmt"
)
func findType(i interface{}) {
switch i.(type) {
case string:
fmt.Printf("I am a string and my value is %s\n", i.(string))
case int:
fmt.Printf("I am an int and my value is %d\n", i.(int))
default:
fmt.Printf("Unknown type\n")
}
}
func main() {
findType("Naveen")
findType(77)
findType(89.98)
}
switch后面的表达式的值将会与case从句中指定的类型进行比较,如果匹配,则执行后续的语句。
I am a string and my value is Naveen
I am an int and my value is 77
Unknown type
也可以将类型与接口进行比较。如果我们有一个类型,并且该类型实现了一个接口,则可以将该类型与其实现的接口进行比较。
package main
import "fmt"
type Describer interface {
Describe()
}
type Person struct {
name string
age int
}
func (p Person) Describe() {
fmt.Printf("%s is %d years old", p.name, p.age)
}
func findType(i interface{}) {
switch v := i.(type) {
case Describer:
v.Describe()
default:
fmt.Printf("unknown type\n")
}
}
func main() {
findType("Naveen")
p := Person{
name: "Naveen R",
age: 25,
}
findType(p)
}
在以上的程序中,类型Person实现了接口Describer, 因此当我们传入一个具体的实例时,它会匹配第一个子句,所以会执行后面的语句,而字符串类型并没有实现这个接口,因此默认执行default子句。
输出结果
unknown type
Naveen R is 25 years old