美文网首页
Golang类型转换和类型断言

Golang类型转换和类型断言

作者: lkzy | 来源:发表于2019-11-12 17:01 被阅读0次

    零值

    变量声明时没有初始化会默认赋值为零值 。
    零值是:

    数值类型为 0 
    布尔类型为 false 
    字符串为 "" (空字符串)
    

    基本类型的类型转换

    C语言转换

    先看一下,在C语言中的类型转换,
    隐式转换

    int a = 10;
    int b = 3.0
    int num = 3.14;  
    double res = a/b;
    

    显示转换

    int a = 10;
    int b = 3.0
    double res = (double)a/b;
    

    Golang基本类型间只能进行显示转换

    但是,Golang基本类型间只能进行显示转换,
    转换形式如下:

    Type(value)
    

    其中value是要转换的值(包括变量、复杂算子和函数返回值),Type是要转换成的类型。
    在类型转换时,要考虑它们之间的关系和范围,以免精度丢失或数值截断。

    特别注意:
    byte --> uint8 和 rune --> int32 是能够直接赋值的特殊情况(byte就是unit8的别名,rune就是int32的别名)

    看一些例子:

        // 输出各数值范围
        fmt.Println("int8 range:", math.MinInt8, math.MaxInt8)
        fmt.Println("int16 range:", math.MinInt16, math.MaxInt16)
        fmt.Println("int32 range:", math.MinInt32, math.MaxInt32)
        fmt.Println("int64 range:", math.MinInt64, math.MaxInt64)
    
        // 初始化一个32位整型值
        var a int32 = 1047483647
        // 输出变量的十六进制形式和十进制值
        fmt.Printf("int32: 0x%x %d\n", a, a)
    
        // 将a变量数值转换为十六进制, 发生数值截断
        b := int16(a)
        // 输出变量的十六进制形式和十进制值
        fmt.Printf("int16: 0x%x %d\n", b, b)
    
        // 将常量保存为float32类型
        var c float32 = math.Pi
        // 转换为int类型, 浮点发生精度丢失
        fmt.Println(int(c))
    

    bool不能直接转换成整型

    bool类型不能强制转换为整型(bool类型在底层是0和1,不能更改为整型变量)

    //bool不能直接转换成int,编译器会报错
    var flag bool = false
    var num int = int(flag) //报错
    fmt.Printf("%d\n", num)
    

    string与基本数据类型转换

    string-->基本数据类型

    • strconv.ParseXxx()
    • strconv.Atoi()
    string-->整型
        /*------strconv.ParseInt------*/
    
        //十进制
        var str string = "4"
        //转换成int8,int8范围-128~127
        num, err := strconv.ParseInt(str, 10, 8)
        if err != nil {
            fmt.Printf("转换失败\n")
        } else {
            fmt.Printf("%d\n", num)
            fmt.Printf("%T\n", num)
        }
    
        //十进制
        var str1 string = "233"
        //转换成int8,int8范围-128~127
        num1, err1 := strconv.ParseInt(str1, 10, 8)
        //233超过8位的长度,转换失败
        if err1 != nil {
            fmt.Printf("转换失败\n")
        } else {
            fmt.Printf("%d\n", num1)
            fmt.Printf("%T\n", num1)
        }
    
        //二进制
        var str2 string = "1001"
        //转换成int32
        num2, err2 := strconv.ParseInt(str2, 2, 32)
        if err2 != nil {
            fmt.Printf("转换失败\n")
        } else {
            fmt.Printf("%d\n", num2)
            fmt.Printf("%T\n", num2)
        }
    
        /*------strconv.Atoi------*/
    
        //10进制
        var str3 string = "9" //会转换成功
        //var str string = "9a"   //会转换失败
        num3, err3 := strconv.Atoi(str3)
        if err3 != nil {
            fmt.Printf("转换失败\n")
        } else {
            fmt.Printf("%d\n", num3)
            fmt.Printf("%T\n", num3)
        }
    
    string-->浮点型
        var str string = "3.1234567890123456789"
        num, err := strconv.ParseFloat(str, 32)
        if err != nil {
            fmt.Printf("转换失败\n")
        } else {
            fmt.Println(num)
            fmt.Printf("%T\n", num)
        }
    
    string-->布尔型
        //str的值可以是1、t、T、TRUE、true、True,
        //也可以是0、f、F、FALSE、false、False
        var str string = "F"
        //直接传入字符串
        flag, err := strconv.ParseBool(str)
        if err != nil {
            fmt.Printf("转换失败\n")
        } else {
            // 注意点: 在Go语言中%t输出布尔类型
            fmt.Printf("%t\n", flag) //false
            fmt.Printf("%T\n", flag) //bool
        }
    

    基本数据类型-->string

    • strconv.FormatXxx()
    • strconv.iota()
    整型-->string
        /*------strconv.FormatInt------*/
    
        var num int = 724
        //转换为10进制格式
        str := strconv.FormatInt(int64(num), 10)
        fmt.Printf("十进制:%s\n", str) //输出:724
        //转换为2进制格式
        str2 := strconv.FormatInt(int64(num), 2)
        fmt.Printf("二进制:%s\n", str2) //输出:1011010100
        //转换为16进制格式
        str16 := strconv.FormatInt(int64(num), 16)
        fmt.Printf("十六进制:%s\n", str16) //输出:2d4
    
        /*------strconv.Itoa------*/
    
        var num4 int32 = 724
        var str7 string = strconv.Itoa(int(num4))
        fmt.Printf("十进制:%s\n", str7) //输出:724
    
    浮点型-->string
        var num2 float32 = 3.1234567890123456789
        var str3 string = strconv.FormatFloat(float64(num2), 'f', -1, 32) // "3.1234567"
        var str4 string = strconv.FormatFloat(float64(num2), 'f', -1, 64) // "3.123456789012345" 
        var str5 string = strconv.FormatFloat(float64(num2), 'f', 2, 32)  // "3.12"
        fmt.Printf("%s\n%s\n%s\n", str3, str4, str5)
    
    bool-->string
        var flag bool = false
        var str6 string = strconv.FormatBool(flag)
        fmt.Printf("%s\n", str6) //false
    

    time转换

    注意:time不是基本类型,但是为了方便整理也放于此处。

        //获取当前时间戳,纳秒
        nanoSeconds := time.Now().UnixNano()
        fmt.Printf("当前纳秒时间戳:%d\n", nanoSeconds)
        fmt.Printf("%T\n", nanoSeconds)
        //纳秒转毫秒
        fmt.Println(nanoSeconds / 1e6)
        //纳秒转秒
        fmt.Println(nanoSeconds / 1e9)
    
        //获取当前时间戳,秒
        seconds := time.Now().Unix()
        fmt.Printf("当前秒时间戳:%d\n", seconds)
        fmt.Printf("%T\n", seconds)
    
        //将纳秒时间戳转换成时间
        t := time.Unix(0, 1573541938000*1e6) //将纳秒转换为 time 类型
        fmt.Printf("时间戳转换成时间格式:%s\n", t.String())
    
        //时间格式化成string
        formatStr := time.Now().Format("2006-01-02 15:04:05.000")
        fmt.Printf("时间格式化成string:%s\n", formatStr)
    
        //将年月日转换成时间
        yearTime := time.Date(2014, 1, 7, 5, 50, 4, 123*1e6, time.Local)
        yearUnix := yearTime.UnixNano()
        fmt.Printf("年月日转换成时间秒时间戳:%d\n", yearUnix)
        yearFormat := yearTime.Format("2006-01-02 15:04:05.000")
        fmt.Printf("年月日转换成时间:%s\n", yearFormat)
    

    interface{}类型转换和类型断言

    • 类型转换在编译期完成,包括强制转换(类型间、接口向类型、类型向接口转换)和隐式转换(类型向接口转换)
    • 类型断言在运行时确定,包括安全类型断言和非安全类型断言
      Go语言要求不同类型之间必须做显式的类型转换。但似乎涉及到接口类型时,就会有所不同。

    类型断言

    //animal 动物
    type animal interface {
        //run 跑
        run()
    }
    
    //duck 鸭子
    type duck struct {
        //name 名称
        name string
        //legNum 腿的数量
        legNum int
    }
    
    func newDuck() duck {
        return duck{
            name:   "duck",
            legNum: 2,
        }
    }
    func (d duck) run() {
        fmt.Printf("在%d,%s跑步用%d条腿\n", time.Now().Unix(), d.name, d.legNum)
    }
    
    //cat 猫
    type cat struct {
        //name 名称
        name string
        //legNum 腿的数量
        legNum int
    }
    
    func newCat() cat {
        return cat{
            name:   "cat",
            legNum: 4,
        }
    }
    func (c cat) run() {
        fmt.Printf("在%d,%s跑步用%d条腿\n", time.Now().Unix(), c.name, c.legNum)
    }
    
    func runWithRecover(a animal) {
        defer func() {
            fmt.Println("end")
            if err := recover(); err != nil {
                fmt.Printf("received panic ,the error is %s\n", err) // 这里的err其实就是panic传入的内容
            }
        }()
        i1 := a.(cat)
        i1.run()
    }
    
    //类型断言的方式
    
    //typeAssert 类型断言的方式
    func typeAssert() {
    
        //第一种
        var d animal
        d = newDuck()
        //不安全的类型断言,如果系统检测到不匹配,会在运行时调用内置的panic,抛出异常
        i := d.(duck)
        i.run()
        //由于不安全断言会抛panic
        runWithRecover(d)
    
        //安全的类型断言。 其中ok为一个bool值, 表征类型转换是否成功; s为返回的int变量,如果失败返回该类型的零值
        if inst, ok := d.(duck); ok {
            inst.run()
        }
        if inst, ok := d.(cat); ok {
            inst.run()
        } else {
            fmt.Printf("assert error,the error is %t\n", ok)
        }
    
        //第二种,type是关键字 结合switch case使用
        switch inst := d.(type) {
    
        case duck:
    
            inst.run()
        case cat:
            inst.run()
        default:
    
            fmt.Println("unknow")
    
        }
    }
    

    相关文章

      网友评论

          本文标题:Golang类型转换和类型断言

          本文链接:https://www.haomeiwen.com/subject/uzrcvctx.html