Go语言之类型断言
一、基础
什么是类型断言呢?
举个例子,我们在之前的Usb接口案例中,假如Phone这个结构体除了实现接口的方法外,它还有自己定义的一个单独方法,但是Carema没有,那么当传入到Computer的use方法中就需要进行类型判断,如果是Phone结构体类型还需要执行额外的方法。
所以类型断言是由于接口不知道具体类型,如果要转成具体类型,就需要使用类型断言。
package main import "fmt" func main() { var i interface{} var a float64 = 6.32 i = a //空接口可以接收任意数据类型 // 使用类型断言 b := i.(float64) fmt.Printf("b的类型为%T 值为%v", b, b) // b的类型为float64 值为6.32 }
在进行类型断言时,如果类型不匹配就会报panic错误,因此在进行类型断言时,确保原来的空接口指向的就是断言的类型。当然你也可以通过检测机制,就是使用返回值来进行判断,避免panic错误的产生。
package main import "fmt" func main() { var i interface{} var a float64 = 6.32 i = a //空接口可以接收任意数据类型 // 使用类型断言,检测机制,避免panic错误 b, flag := i.(float64) if flag { fmt.Printf("b的类型为%T 值为%v", b, b) // b的类型为float64 值为6.32 } else { fmt.Println("类型转换失败") } }
二、最佳实践
1、案例一
如果在Phone结构体中额外增加talking方法,那么在Computer中的use方法中就需要使用断言来判断了。
package main import "fmt" // 定义一个接口 type Usb interface { // 声明两个未实现的方法 start() stop() } // 声明一个Phone的结构体 type Phone struct { } // Phone结构体变量接口实现方法 func (phone Phone) start() { fmt.Println("手机开始工作...") } func (phone Phone) stop() { fmt.Println("手机结束工作...") } // Phone结构体变量中额外的方法 func (phone Phone) talking() { fmt.Println("正在通话中...") } // 声明一个Camera的结构体 type Camera struct { } // Camera结构体变量接口实现方法 func (camera Camera) start() { fmt.Println("相机开始工作...") } func (camera Camera) stop() { fmt.Println("相机结束工作...") } // 声明一个Computer结构体 type Computer struct { } // usb会自动根据传递过来的来判断是phone还是camera然后调用对应的结构体变量中实现的方法 func (computer Computer) use(usb Usb) { usb.start() usb.stop() // 使用断言 phone, flag := usb.(Phone) if flag { phone.talking() } } func main() { // 创建结构体变量 computer := Computer{} phone := Phone{} camera := Camera{} computer.use(phone) computer.use(camera) } /* 手机开始工作... 手机结束工作... 正在通话中... 相机开始工作... 相机结束工作... */
2、案例二
类型判断,写一个函数来循环判断传入的参数类型。
package main import "fmt" func JudgeType(items ...interface{}) { for index, value := range items { switch value.(type) { case bool: fmt.Printf("第%v个参数时bool类型,值为%v\n", index, value) case float32: fmt.Printf("第%v个参数时float32类型,值为%v\n", index, value) case float64: fmt.Printf("第%v个参数时float64类型,值为%v\n", index, value) case int: fmt.Printf("第%v个参数时int类型,值为%v\n", index, value) case string: fmt.Printf("第%v个参数时string类型,值为%v\n", index, value) default: fmt.Printf("第%v个参数类型不确定,值为%v\n", index, value) } } } func main() { var a int = 10 var b string = "happy" var c float32 = 3.21 JudgeType(a, b, c) }