1.基本介绍
类型断言,由于接口是一般类型,不知道具体类型,如果要转换成具体类型,就需要使用类型断言
package main
import(
"fmt"
)
type Point struct{
x int
y int
}
func main() {
var a interface{}
var point Point = Point{1, 2}
a = point //ok
//如何将a赋给一个Point变量
var b Point
//b = a //可以吗? ==> cannot use a (type interface {}) as type Point in assignment: need type assertion
b = a.(Point)//可以(类型断言)
fmt.Println(b)
//类型断言的其他案例
var x interface{}
var c float32 = 2.2
x = c //x是空接口,可接收任意类型
//x ==> float32[使用类型断言]
y := x.(float32) //必须知道原来的x空接口是什么类型,这样才能够转换回去,不然会报错panic
fmt.Printf("y 的类型%T, 值%v\n", y, y)//y 的类型float32, 值2.2
}
对上面代码的说明:
在进行类型断言时,如果类型不匹配,就会报panic,因此进行类型断言时,要确保原来的空接口指向的就是断言的类型
2.案例
package main
import(
"fmt"
)
type Point struct{
x int
y int
}
func main() {
var a interface{}
var point Point = Point{1, 2}
a = point //ok
//如何将a赋给一个Point变量
var b Point
//b = a //可以吗? ==> cannot use a (type interface {}) as type Point in assignment: need type assertion
b = a.(Point)//可以(类型断言)
fmt.Println(b)
// //类型断言的其他案例
// var x interface{}
// var c float32 = 2.2
// x = c //x是空接口,可接收任意类型
// //x ==> float32[使用类型断言]
// y := x.(float32) //必须知道原来的x空接口是什么类型,这样才能够转换回去,不然会报错panic
// fmt.Printf("y 的类型%T, 值%v\n", y, y)//y 的类型float32, 值2.2
//带检测的类型断言
var x interface{}
var c float32 = 2.2
x = c //x是空接口,可接收任意类型
//x ==> float32[使用类型断言]
y, ok := x.(float64) //必须知道原来的x空接口是什么类型,这样才能够转换回去,不然会报错panic
if ok {
fmt.Println("成功")
fmt.Printf("y 的类型%T, 值%v\n", y, y)//y 的类型float32, 值2.2
} else {
fmt.Println("失败")
}
fmt.Println("继续执行")
//上面代码简洁写法
if y, ok := x.(float64); ok {
fmt.Println("成功")
fmt.Printf("y 的类型%T, 值%v\n", y, y)//y 的类型float32, 值2.2
} else {
fmt.Println("失败")
}
fmt.Println("继续执行")
}
3.类型断言的最佳实践
在前面的Usb接口案例做改进:
给Phone结构体增加一个特有的方法call(),当Usb接口接收的是Phone变量时,还需要调用call方法
package main
import(
"fmt"
)
// 声明一个接口
type Usb interface {
//声明了两个没有实现的方法
Start()
Stop()
}
//声明一个结构体,实现Usb方法
type Phone struct{
Name string
}
func (p Phone) Start() {
fmt.Println("手机开始工作...")
}
func (p Phone) Stop() {
fmt.Println("手机停止工作...")
}
func (p Phone) Call() {
fmt.Println("手机打电话...")
}
//相机实现Usb方法
type Camera struct{
Name string
}
func (c Camera) Start() {
fmt.Println("相机开始工作...")
}
func (c Camera) Stop() {
fmt.Println("相机停止工作...")
}
//计算机
type Computer struct{
}
//编写一个方法Working, 接收一个Usb接口类型变量
//实现了Usb接口(就是指实现了Usb接口声明的所有方法)
func (c Computer) Working(usb Usb) {
//通过Usb接口变量来调用Start,Stop方法
usb.Start()
//如果usb指向Phone结构体变量,则还需调用Call()
//类型断言
if phone, ok := usb.(Phone); ok {
phone.Call()
}
usb.Stop()
}
func main() {
//定义一个Usb接口数组,可以存放Phone,Camera的结构体变量
//体现多态数组
var usbArr [3]Usb
usbArr[0] = Phone{"华为"}
usbArr[1] = Phone{"小米"}
usbArr[2] = Camera{"相机"}
fmt.Println(usbArr)
//遍历usbArr
//Phone还有一个特定的方法Call(),遍历Usb数组,如果是Phone变量,
//除了调用Usb接口声明的方法外,还需调用Phone特有的方法Call() ==> 类型断言
var computer Computer
for _, v := range usbArr {
computer.Working(v)
}
}
编写一个函数,判断输入的参数是什么类型
package main
import(
"fmt"
)
//编写一个函数,判断输入的参数是什么类型
func TypeJudge(items... interface{}) {
for index, v := range items {
switch v.(type) {
case bool:
fmt.Printf("第%v个参数的类型是bool,值为%v\n", index, v)
case float32:
fmt.Printf("第%v个参数的类型是float32,值为%v\n", index, v)
case float64:
fmt.Printf("第%v个参数的类型是float34,值为%v\n", index, v)
case int, int32, int64:
fmt.Printf("第%v个参数的类型是int,值为%v\n", index, v)
case string:
fmt.Printf("第%v个参数的类型是string,值为%v\n", index, v)
default:
fmt.Printf("第%v个参数类型不正确", index)
}
}
}
func main() {
var n1 float32 = 1.1
var n2 float64 = 2.21
var n3 int32 = 3
var n4 string = "golang"
name := "张三"
n5 := 10
TypeJudge(n1, n2, n3, n4, name, n5)
}
第0个参数的类型是float32,值为1.1
第1个参数的类型是float32,值为2.21
第2个参数的类型是int,值为3
第3个参数的类型是string,值为golang
第4个参数的类型是string,值为张三
第5个参数的类型是int,值为10
package main
import(
"fmt"
)
type Student struct {
Name string
}
//编写一个函数,判断输入的参数是什么类型
func TypeJudge(items... interface{}) {
for index, v := range items {
switch v.(type) {
case bool:
fmt.Printf("第%v个参数的类型是bool,值为%v\n", index, v)
case float32:
fmt.Printf("第%v个参数的类型是float32,值为%v\n", index, v)
case float64:
fmt.Printf("第%v个参数的类型是float34,值为%v\n", index, v)
case int, int32, int64:
fmt.Printf("第%v个参数的类型是int,值为%v\n", index, v)
case string:
fmt.Printf("第%v个参数的类型是string,值为%v\n", index, v)
case Student:
fmt.Printf("第%v个参数的类型是Student,值为%v\n", index, v)
case *Student:
fmt.Printf("第%v个参数的类型是*Student,值为%v\n", index, v)
default:
fmt.Printf("第%v个参数类型不正确", index)
}
}
}
func main() {
var n1 float32 = 1.1
var n2 float64 = 2.21
var n3 int32 = 3
var n4 string = "golang"
name := "张三"
n5 := 10
stu := Student{
Name : "李四",
}
stu2 := &Student{
Name : "王五",
}
TypeJudge(n1, n2, n3, n4, name, n5, stu, stu2)
}
第0个参数的类型是float32,值为1.1
第1个参数的类型是float34,值为2.21
第2个参数的类型是int,值为3
第3个参数的类型是string,值为golang
第4个参数的类型是string,值为张三
第5个参数的类型是int,值为10
第6个参数的类型是Student,值为{李四}
第7个参数的类型是*Student,值为&{王五}