[go学习笔记.第十章.面向对象编程] 12.类型断言引出和基本使用

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,值为&{王五}

[上一节][go学习笔记.第十章.面向对象编程] 11.面向对象的三大特性-多态

[下一节][go学习笔记.第十一章.项目案例] 1.家庭收支记账软件项目 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值