开发者学堂课程【Go语言核心编程 - 面向对象、文件、单元测试、反射、TCP编程:反射的注意事项和细节(1)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/626/detail/9770
反射的注意事项和细节(1)
内容介绍
一、Reflect.Value.Kind,获取变量的类别,返回的是一个常量
二、Type 和 Kind 的区别
三、变量之间相互转换
四、数据类型匹配
一、Reflect.Value.Kind,获取变量的类别,返回的是一个常量
Reflect.Value.Kind,获取变量的类别,返回的是一个常量,这是反射的第一个细节,在这了引出了一个 const 的内容。现在看反射第二个所需要注意的地方。Type 是类型,Kind 是类别,Type 和 Kind 可能是相同的,也可能是不同的。 它可能取决于传进去做反射的变量是什么类型的。如果是一个基本数据类型,比如像 float、boolen,那这个 Type 和 Kind 其实是相同的,就不存在包的问题。如果是像 student 这种结构体的话,它的 Type 是包名 student,Kind 就是 struct。那就意味着 student 这个结构体也允许是别的包。在 golang 里面去区分一个 type 是包名加结构体的名称,比如在 pkg1这个包下面有一个 student,它算是一个 type。也有可能在 pkg2下面也有一个 student,这个是不冲突的。在 golang 里面是以包名来进行范围的一个区分的。两个 student 的类型是不一样的,但类别是一样的,都是结构体。第一点是对于获取类别返回的常量做了一个说明。
二、Type 和 Kind 的区别
第二点讲了 Type 和 Kind 的一个区别。Type 是类型,Kind 是类别,两者可能相同也可能不同,这需要根据变量的类型进行区分。
比如:var num int=10 num 的 Type 是int,Kind 也是 int
var stu student stu 的 Type 是 pkg1.student,Kind 是 struct
三、变量之间相互转换
通过反射可以让变量在 interface 和 Reflect value 之间相互转换,刚才所讲的案例不管是基于基本数据类型的还是基于结构体的,它们之间可以相互转换。变量可以交给 interface,interface 可以转成 reflect .value,两者又可以转回去。这个箭头是双向的。
四、数据类型匹配
使用反射的方式来获取变量的值(并返回对应的类型),要求数据类型匹配。比如 x 是 int,在反射的时候就应该先拿到 reflect .value,再去取它的值,而不能使用其它的,否则就会报 panic。再讲反射的时候专门强调了 n2 :=2﹢rVal.Int,取它重点的值这个细节强调通过反射来获取变量的值要怎样去做。如果要取出一个结构体的话,会发现这个 value 没有直接的结构体,那只能用断言了。因为结构体对应的 type 类型是无法确定的,对于结构体需要先断言再取才可以。如果给接口传的是 int 类型,但是用 float 去取,那这里就会直接报错。比如很清楚的知道
Reflect01Test(b interface{}),这个 b 是100传进来的。应该要 n2 :=2﹢rVal.Int 这样去取,但偏偏要 n3 :rVal.Float() 这样用 Float 去取,会发现在编译这个层面找不到。无论是用 int 来取还是 float 来取都是属于运行时态了。rVal 其实是一个持有 int 类型的一个反射值,但要把它变成 float,那么错误就会第二层面发生。第二次行应该报错,因为它在运行的时候发现有问题。比对数据类型的话可以加判断,强调 reflect .value 这种类型去取回对应的基本数据类型,一定要确认是同一个类型。