Go语言基础之反射

Go语言基础之反射

前言

Hey,大家好呀,我是码农,星期八!,我们以前学的呀,都属于正向定义变量,正向开发!

但是有没有什么办法能反着来呢?根据变量获取类型等操作。

一起来看看Go的反射吧!!!

什么是反射

反射,嗯…,就是反着的意思呗,就是把东西反过来。

比如这样的一个很简单的代码。

var a int = 3
fmt.Println(a)

我们当然知道a变量是int类型,但是反过来想,程序是怎么知道aint类型呢???

这时候,就需要用到反射了。

示例代码

v := reflect.TypeOf(a)
fmt.Println(v)

两次代码综合一块执行结果

在这里插入图片描述

第二次的第2行代码,成功的将变量a还原出了int类型。

什么???你为我有什么用???,嗯。。。实话实说,用的不是太多,但是必须要会的。

反射(reflect包)

在Go中,任何变量,都有具体类型具体值,就像var a int = 3具体类型就是int具体值就是3

所以,变量的具体类型归属在reflect.Type,变量的具体值归属在reflect.Value

并且Go的提供了

  • reflect.TypeOf获取具体类型

  • reflect.ValueOf获取具体值

TypeOf

TypeOf方法可以获取变量的具体类型

有一个这样的需求,定义一个函数,可以接收任意类型数据,通过反射打印变量类型。

示例代码
函数
func reflectType(x interface{}) {
	v := reflect.TypeOf(x)
	fmt.Printf("你传入的变量类型是:%v\n",v)
}
main
func main() {
	var a int = 666
	var b float64 = 3.14
	var c string = "hello world"
	var d [3]int = [3]int{126}
	var e []int = []int{12688}
	var f map[string]interface{} = map[string]interface{}{
		"Name":"张三""Age":18}
	reflectType(a)
	reflectType(b)
	reflectType(c)
	reflectType(d)
	reflectType(e)
	reflectType(f)
}
执行结果

在这里插入图片描述

通过reflect.TypeOf方法,完美解决上述需求。

TypeOf 的Name和Kind

这个是啥意思呢??这个在结构体中比较好体现。

简答来说就是TypeOf返回的太笼统了,还有更加细化的类型,通过这俩属性获取。

示例代码
函数
func reflectType(x interface{}) {
	v := reflect.TypeOf(x)
	fmt.Printf("你传入的变量类型是:%v | Name:%v | Kind:%v\n", v, v.Name(), v.Kind())
}
结构体
type Student struct {
	Name string
	Age int
}
main
func main() {
	var a int
	var b *int
	var c []int
	var d map[string]interface{}
	var e Student
	reflectType(a)
	reflectType(b)
	reflectType(c)
	reflectType(d)
	reflectType(e)
}
执行结果

在这里插入图片描述

总结

经过对比,会发现几个特殊问题。

如果变量是指针类型Name为空,Kindptr

如果变量是引用类型(切片和map)类型,Name为空,只有Kind

如果变量是结构体Name是结构体名,Kindstruct

ValueOf

TypeOf只能反过来获取变量的具体类型,但是并不能获取具体值,这就有点不太厚道了。

所以ValueOf就来解决这个问题了,但是ValueOf牛叉的是,它里面还包括了变量类型

注:ValueOfTypeOfKind属性返回内容是一摸一样的。

需求:定义一个函数,可以接收任意类型,通过反射得出变量类型和变量值。

函数
func reflectType(x interface{}) {
	v := reflect.ValueOf(x)
	k := v.Kind()
	switch k {
	case reflect.Int:
		fmt.Printf("我是Int类型,我的值是%v\n",v.Int())
	case reflect.Slice:
		fmt.Printf("我是切片类型,我的值是%v\n",v.Slice(12))
	case reflect.Map:
		fmt.Printf("我是切片类型,我的值是%v\n",v.MapKeys())
	//case :可以继续case下去
	}
}
main
func main() {
	var a int = 1
	var c []int = []int{15719}
	var d map[string]interface{} = map[string]interface{}{
		"Name": "你好""Age":  18}
	var e Student
	reflectType(a)

	reflectType(c)
	reflectType(d)
	reflectType(e)
}
执行结果

在这里插入图片描述

通过反射设置值

反射还有一个用途,就是动态的修改变量值,可能你暂时体会不到,但是语法还是要学的。

通过反射设置值,需要用到Elem方法,并且传入的必须是指针

示例代码

函数
func reflectSetValue(x interface{}) {
	v := reflect.ValueOf(x)
	//kind也必须是Elem调用
	var k = v.Elem().Kind()
	switch k {
	case reflect.Int:
		//反射修改必须通过Elem
		v.Elem().SetInt(200)
	}
}
main
func main() {
	var a int = 10
	fmt.Printf("a的值:%v\n", a)
	//反射修改值传入的必须是地址
	reflectSetValue(&a)
	fmt.Printf("a的值:%v\n", a)
}
执行结果

在这里插入图片描述

总结

上述我们学习了Go基础反射的TypeOfTypeOf的Name和KindValueOf通过反射设置值

其中KindTypeValueOf中都有,通常情况下TypeOfValueOf一起使用效果更佳!

反射这一块,可能不是那么好理解,一定要多多下功夫!,坚持!!

如果在操作过程中有任何问题,记得下面留言,我们看到会第一时间解决问题。

我是码农星期八,如果觉得还不错,记得动手点赞一下哈。

感谢你的观看。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值