Golang类型转换和类型断言

零值

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

数值类型为 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类型转换和类型断言)