强制类型转换

从问题开始,今天我想对一个struct的数组强制转为[]interface{},发现报错,报错显示:Invalid type assertion。所以到底是咋回事呢?趁这个机会,抓紧补习下golang的类型转换,有哪些方式,以及有哪些方式是不允许类型转换的,还有就是自动类型转换发生在哪些情况下。

golang的类型转换分为强制类型转换和类型断言,下面就从这两个方面入手:

强制类型转换

普通类型变量(int,float,string)都是用type(a)的形式进行类型转换,举如下例子:

var a int32  = 10
var b int64 = int64(a)
var c float32 = 12.3
var d float64 =float64(c)

一般来讲int32、int64、int8之间可以通过强制类型互相转换,但是从长度大的int转到长度小的Int时,就需要考虑溢出问题了,这个是需要注意的,看下下面代码:

    var intTest32 int32 = 2147483647
    var intTest64 int64 = 2147483648
    intTest32 = int32(intTest64)
    fmt.Println(intTest32)
    fmt.Println(intTest64)

结果:

-2147483648
2147483648

再看看下面普通类型转换报错的代码:

func main() {
    i := 0
    var a float32
    a = 0.9
    i = a //cannot use `a` (type float32) as type int assignment
    var b float64
    b = a//cannot use `a` (type float32) as type float64 assignment
    var intTest int32
    intTest = 12
    var intTest2 int8
    intTest2 = intTest ////cannot use `intTest` (type int32) as type int8 assignment
}

得出来的结论是:普通类型无法自动进行类型转换,就算是Int8到int32都不能自动转换。

顺便看下int,int8,int32,int64的区别,参见https://golang.google.cn/ref/spec#Numeric_types

比如int8是8位bit组成的,范围在-128到127。你可以通过unsafe.sizeof函数查看int8的大小。

结果是:

看下unsafe.Sizeof的注释:

所以Int8、int32、int64之间只是用来存储的bit个数不一样,默认int是int64,所以大家平时要根据需要申请,别直接Int。

OK,强制类型转换就说到这。下面说下类型断言。

类型断言

首先golang所有类型都实现了interface{},就像Java语言中的Object对象,golang中自定义的struct都是实现interface{}的,所以一般类型都能转换为Interface{}。但是Interface{}能直接强制类型转换为普通类型吗?比如string。实践一下就知道了:

结果:

下面测试下Interface{}能否直接强制类型转换为普通类型

上面例子显示interface{}强转string会报错,但是我们明明知道这是string,但是转不了,咋办呢?这就需要用到类型转换了:

结果:

我觉得这样的断言设计是为了在运行时动态判断传送过来的数据类型,进行动态避错,减少bug的发生,也能增强接口的容错性。就算转换不成功,也会有结果值,这样就非常好了,如下:

结果:

所以,就算类型转换不成功,他也会帮你把结果值初始化为你要转换类型的零值。这样的设计非常的好。我们在使用时也不需要强迫自己去判断Ok是否为true,反正有零值返回。当然也要看零值是否是你所需要的。

总结下:我个人比较喜欢类型断言,设计的非常棒

csdn博客:https://blog.csdn.net/u013276277

参考文章:

https://studygolang.com/articles/21591

https://draveness.me/golang/docs/part1-prerequisite/ch02-compile/golang-typecheck/

https://golang.org/doc/faq#convert_slice_of_interface

推荐以下golang语言相关的问题可以去看下这个地址:https://golang.org/doc/faq

最后更新于

这有帮助吗?