• 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)
    }
  • 相关阅读:
    Redis安装测试
    linux 查看磁盘空间大小
    冷备份与热备份、双机热备与容错
    IDEA在编辑时提示could not autowire
    IntelliJ IDEA 快捷键和设置
    POI实现EXCEL单元格合并及边框样式
    metaq架构原理
    二叉树
    开启“树”之旅
    巧妙的邻接表(数组实现)
  • 原文地址:https://www.cnblogs.com/shenjianping/p/15829161.html
Copyright © 2020-2023  润新知