Go:类型断言
一、基本介绍
类型断言:由于接口是一般类型,不知道具体类型,如果要转成具体类型,就需要使用类型断言。
如果希望将一个空接口类型重新转换成对应的类型,那么需要使用类型断言,能转换成功是因为这个空接口原先是指向这个类型的。
type Point struct { x int y int } func main() { var a interface{} var p = Point{1, 2} a = p // 这是可以的 var b Point //b = a // 这时不可以的,要使用断言,如下 b = a.(Point) // 这就是类型断言,表示看看能不能将 a 转换成 Point,再赋给 b c := a.(Point) fmt.Println(b) // {1 2} fmt.Printf("c的类型=%T,值=%v", c, c) // c的类型=main.Point,值={1 2} }
二、带检测的类型断言
在进行类型断言时,如果类型不匹配,就会报 panic,因此在进行类型断言时,需要检测机制,如果成功就继续执行,否则不要报 panic。
type Point struct {
x int
y int
}
func main() {
var a interface{}
var p = Point{1, 2}
a = p
b, ok := a.(int) // 肯定转换失败的,如果是string,则 b 为空
if ok{
fmt.Println("转换成功")
} else {
fmt.Println("转换失败") // 转换失败
}
fmt.Println(b) // 0
}
三、类型断言最佳实践
示例1:
type Usb interface { Connect() Disconnect() } type Phone struct {Name string} type Camera struct {Name string} func (p Phone) Connect() {fmt.Printf("%s连接中...\n", p.Name)} func (p Phone) Disconnect() {fmt.Printf("%s断开连接中...\n", p.Name)} func (c Camera) Connect() {fmt.Printf("%s连接中...\n", c.Name)} func (c Camera) Disconnect() {fmt.Printf("%s断开连接中...\n", c.Name)} // Phone结构体特有的方法Call func (p Phone) Call() {fmt.Printf("正在使用%s打电话,..\n", p.Name)} type Computer struct {} func (c Computer) Working(usb Usb) { usb.Connect() usb.Disconnect() // 如果 usb 是指向 Phone 结构体变量,则还需要调用 Call 方法 phone, ok := usb.(Phone) // 类型断言 if ok { phone.Call() } } func main() { // 定义一个 Usb 接口数组,可以存放 Phone 和 Camera 结构体的实例 var usbArr [2]Usb usbArr[0] = Phone{"苹果"} usbArr[1] = Camera{"尼康"} var computer Computer for _, v := range usbArr { computer.Working(v) } fmt.Println() fmt.Println(usbArr) }
示例2:
type Student struct {} func TypeJudge(args... interface{}) { for i, v := range args { switch v.(type) { case int, int8, int16, int32, int64: fmt.Printf("第%v个参数是 整数 类型,值是%v\n", i, v) case float32: fmt.Printf("第%v个参数是 float32 类型,值是%v\n", i, v) case float64: fmt.Printf("第%v个参数是 float64 类型,值是%v\n", i, v) case bool: fmt.Printf("第%v个参数是 bool 类型,值是%v\n", i, v) case string: fmt.Printf("第%v个参数是 string 类型,值是%v\n", i, v) case Student: fmt.Printf("第%v个参数是 Student 类型,值是%v\n", i, v) case *Student: fmt.Printf("第%v个参数是 *Student 类型,值是%v\n", i, v) default: fmt.Printf("第%v个参数的类型未知,值是%v\n", i, v) } } } func main() { var a int = 1 var b float32 = 2.2 var c float64 = 3.3 var d bool = true var e Student var f *Student TypeJudge(a, b, c, d, e, f) }