开发者学堂课程【Go 语言核心编程 - 面向对象、文件、单元测试、反射、TCP 编程:反射的快速入门(1)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/626/detail/9768
反射的快速入门(1)
内容介绍
一、案例一
二、案例二简要
一、案例一
请编写一个案例,演示对(基本数据类型、interface{}、reflect.Value) 进行反射的基本操作。
func test01(b interface {}) {
t :=reflect.TypeOf(b)
fmt.Println("type=",t)
v :=reflect.ValueOf(b)
k := v.Kind()
fmt.Println("kind=",k)
fmt.Println("value=",v.Int ())
}
具体代码演示:
打开 main.go,新建一个文件夹 chapter17,再继续在 chapter17 下新建文件夹reflectdemo01,新建文件 main.go,然后输入
package main
import(
“reflect”
“fmt”
)
//专门演示反射
fun reflectTest01(b interface{}) {
//这里一般要用一个接口,因为可以对任何的数据类型进行反射
}
func main(){
//请编写一个案例,
//演示对(基本数据类型、interface{}、reflect.Value) 进行反射的基本操作
}
创建好接口后,接着来定义一个 int,在 func main(){}中输入
//1.先定义一个 int
var num int=100
现在假设是要通过反射来获取 num 的 type 以及该值的即演示通过 number 获取它的一系列信息
先在 func main(){}中输入
reflectTest01(num)
继续在 func reflectTest01(b interface{}){}中输入
//通过反射获取的传入的变量的 type,kind,值(type 是类型,kind 是类别)
//1.先获取到 reflect.Type
rTyp := reflect.TypeOf(b)
//定义为 rTyp 代表以反射形式的 type,没有 r打头为普通 type
fmt.Println(“rType=”,rType)
接着先来测试下结果:
输入cd..
cd chapter17
dir
cd reflectdemo01
go run main.go
结果显示为:rType= int
继续开始第二步,在 func reflectTest01(b interface{}){}
中输入
//2.获取到 reflect.Value
rVal := reflect.ValueOf(b)
fmt.Println(“rVal=”,rVal)
再来运行查看结果,输入go run main.go
显示结果为rType= int
rVal= 100
但是要注意虽然结果显示为100,但是它的值并不真正是100,如果为普通100的话,假设第二步继续定义一个 num,输入
n1 :=10
n2 := 2+n1
fmt.Println(“n2=”, n2)
接着来运行查看结果,结果显示 n2为12,完全正确,那么接着再修改:
删除 n1,修改代码为
n2 :=2+rVal
2后加上反射的值,如果该值为真正100,可以运行成功,但是输入后就会显示报错:invalid operation: 2+ rVal (mismatched types int and reflect.Value)
所以接下来讲解如何真正看类型,注释掉n2 := 2+ rVal
fmt.Println(“n2=”, n2)
修改代码fmt.Printf(“rVal=%v \n”, rVal)
运行结果仍为100没有变化,继续修改
fmt.Printf(“rVal=%v rVal type=”%T\n”, rVal,rVal)
此时再来运行,结果显示rVal=100 rVal type=reflect.Value
完成后回到n2的问题,怎样真正拿到int值,要思考reflectValue是否提供一个方法将它的值真正取出,打开手册,提供了大量方法可以使用
提供了在底层可以通过反射改变值的方法,此外还提供了 int()、Bool() 等方法
查看 int 方法
func (v Value) Int() int64
返回 v 持有的有符号整数(表示为int64),如果 v 的 kind 不是 int、int8、int16、int32、int64 会 panic
这才是真正的值,也就是说在 n2进行+的时候应该写为:
n2 := 2+rVal.Int()
再来运行,结果显示 n2=102,结果正确
解决完后再来继续完成,以上内容完成了将变量交给接口,又通过接口获取了 Type 和反射的 Value,但是现在还有一个需求:重新转为 number,继续在输入
//下面我们将 rVal 转成 interface{}
iV:= rVal.Interface()
//将 interface{}通过断言转成需要的类型
num2 := iV.(int)
fmt.Println(“num2”, num2)
运行结果就为真正的100,结果显示 num2=100
二、案例二简要
下节讲解第二个案例:
请编写一个案例,演示对(结构体类型、interface{}、reflect.Value)进行反射的基本操作。
var stu Student = Student {
Name: "tom",
Age:20,
Score: 77.4,
iv := v.Interface()
//下面的printf不能使用iv.Name
fmt.Printf("iv=%v iv=%T \n", iv, iv)
//将iv转成Sudent
stu,ok := iv.(Student)
if ok {
fmt.Printf("%v %T stu.Name="%v\n",stu,stu,stu.Name)