Go语言中的类型断言,一般用于类型转换,但是这类转换是有限制的
- 类型断言,是将万能类型的
interface{}
x转为自定类型T,格式为:x.(T)
- 类型断言的必要条件就x是接口类型,非接口类型的x不能做类型断言
接下来,我们就来动手实践一番
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package main
import ( "fmt" )
type Person struct { Name string }
func speak(p interface{}) { person := p.(Person) fmt.Println(person.Name) }
func main() { p := Person{Name: "Bob"} speak(p) }
|
在speak
里面的参数为interface{}
,在使用时,我们使用类型断言
将interface{}
转换为Person
。这种断言是基础类型,但是有时候,我们可能会断言失败。我们新建一个类型来看看现象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package main
import ( "fmt" )
type Person struct { Name string }
type Staff struct { Name string }
func speak(p interface{}) { staff := p.(Staff) fmt.Println(staff.Name) }
func main() { p := Person{Name: "Bob"} speak(p) }
|
这时候会报错,并提示
1
| panic: interface conversion: interface {} is main.Person, not main.Staff
|
这时候,我们需要安全的转换,如果转换失败则不往下面执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package main
import ( "fmt" )
type Person struct { Name string }
type Staff struct { Name string }
func speak(p interface{}) { staff, ok := p.(Staff) if ok { fmt.Println(staff.Name) } }
func main() { p := Person{Name: "Bob"} speak(p) }
|
类型断言虽然好用,但是如果因为结构体的字段过多,会导致转换效率比较低,而且不同的数据类型的转换效率也不同。有网友提到,使用指针并转换回相同的结构指针,则会大大提高转换效率,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package main
import ( "fmt" )
type Person struct { Name string }
func speak(p interface{}) { person, ok := p.(*Person) if ok { fmt.Println(person.Name) } }
func main() { p := &Person{Name: "Bob"} speak(p) }
|
虽然interface{}
用起来很爽,但是如果使用不得当,则会对我们的程序造成性能影响。所以,我们要适当、恰当的使用interface{}
。