go学习part20(2)反射细节

1.反射细节

1) reflect.Value.Kind,获取变量的类别,返回的是一个常量(看手册)
 

2)Type是类型,Kind是类别

Type和Kind可能是相同的,也可能是不同的.

比如: var num int = 10 num的Type是int , Kind也是int
比如: var stu Student stu的Type是包名.Student , Kind是struct。

区别理解:Kind指的是在go语言里你的这个变量具体是属于哪一种大类,比如stu属于struct,本质是一个常量,如果是nil表示非法分类。

                Type指的是一个变量具体属于哪一类,比如stu属于学生结构体Student

 

package main

import (
	"fmt"
	"reflect"
)

func reflectTest01(b interface{}) {
	//通过反射获取的传入的变量的 type , kind,值
	//感觉有点像包装一个类型结构体然后绑定String()方法输出内部数值。
	//实际类型是一个包装类型,但是输出内容的都是内部存储类型。
	//1。先获取到 reflect.Type
	rType := reflect.TypeOf(b)
	fmt.Println(rType) //真正类型是reflect.Type,但是输出会自动变成内部存储类型的实际类型int

	//2。先获取到 reflect.Value
	rVal := reflect.ValueOf(b)
	//报错cannot convert 2 (untyped int constant) to type struct{typ *reflect.rtype,
	//说明实际不是int类型而是reflect.Value
	//所以Value提供了很多方法去修改或者读取内部的值
	//n2 := 2 + rVal
	n2 := 2 + rVal.Int() //读取内部Int值
	fmt.Println(n2)
	fmt.Println(rVal) //真正类型是reflect.Value,但是输出会自动变成内部存储类型的实际值
	fmt.Printf("rVal内部数值:%v,rVal真正类型:%T\n", rVal, rVal)

	//3.将rVal转成interface{}
	iV := rVal.Interface() //把内部值按空接口类型输出
	//通过断言把interface{}转成需要的类型
	n3 := iV.(int)
	fmt.Println("n3=", n3)

}

type Student struct {
	Name string
	Age  int
}

// 对结构体反射
func reflectTest02(b interface{}) {
	//1。先获取到 reflect.Type
	rType := reflect.TypeOf(b)
	fmt.Println(rType) //真正类型是reflect.Type,但是输出会自动变成内部存储类型的实际类型int

	//2。先获取到 reflect.Value
	rVal := reflect.ValueOf(b)

	//获取对应Kind,从Value和Type都可以,一模一样
	kind1 := rVal.Kind()
	kind2 := rType.Kind()
	fmt.Printf("kind1内部数值:%v,kind1真正类型:%T\n", kind1, kind1)
	fmt.Printf("kind2内部数值:%v,kind2真正类型:%T\n", kind2, kind2)

	//3.将rVal转成interface{}
	iV := rVal.Interface()                        //把内部值按空接口类型输出
	fmt.Printf("iV 内部数值:%v,iV 真正类型:%T\n", iV, iV) //运行看实际类型,所以输出的是Student类型
	//虽然运行输出可以,但是想调用Student内容是不行的,编译不知道底层实际类型,所以需要通过断言把interface{}转成需要的类型
	stu, ok := iV.(Student) //也可以switch
	if ok {
		fmt.Println("stu.Name=", stu.Name)
	}

}

func main() {
	演示对(基本数据类型、interface{(}、reflect.value)进行反射的基本操作
	//1.定义int
	// var num int = 100
	// reflectTest01(num)

	//2.定义结构体
	stu := Student{
		Name: "tom",
		Age:  20,
	}

	reflectTest02(stu)
}

3. 变量和空接口和Reflect.Value可以相互转换

 4.Reflect.Value调用取基本类型的函数要求类型匹配,取结构体类型只能先断言再用,没有提供函数

5.通过反射的函数来修改变量

注意当使用setXxx方法来设置需要通过对应的指针类型来完成,这样才能改变传入的变量的值,同时需要使用到reflect.Value.Elem()方法

288_尚硅谷_反射的注意事项和细节(2)_哔哩哔哩_bilibili

注意:在反射函数里修改值的时候想要传指针,但是传指针就导致函数里Reflect.Value封装了指针类型的Value,会导致后续无法进行某些操作。

所以需要Elem方法,把一个封装了指针或者接口的Value转换成封装了它们指向(承载)的值的一个封装的Value

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值