Go语言通过反射用字符串字段给结构体变量赋值理解reflect的使用

Go语言通过反射用字符串字段给结构体变量赋值理解reflect的使用

我们知道给一个结构体变量直接赋值可以直接写死

a := struct {
     
		name string
		age int
	}{
     
		name: "haha",
		age: 1,
	}
a.name = "hahaha"

**但是如果我们需要用一个字符串字段给结构体变量赋值,因为字符串有可能是动态传入或者动态获取的,所以就需要用到反射赋值 **

直接上代码


需要注意的是

  • 反射不能设置未被导出的字段,所以上面的字段都是大写
  • 因为要设置内部的值,所以传入ValueOf内部的必须是a的地址值

对反射的理解

使用场景

反射的作用式在运行时,动态获取操作结构体变量,数组内部的值,也就是说当要操作外部传进来的不确定属性的结构体,或者不去确定要操作结构体或数组的那些元素的时候,我们才用反射.

使用反射

反射最外层只有两个方法

  • TypeOf()获取变量的Type(),动态类型也就是外部表象动态类型,
  • ValueOf()获取变量的Value(),也就是值
  • … 其他一些后面可以链式调用的方法直接看文档,比较重要的式Kind()获取底层类型也就是基本类型,Elem()将反射的地址转成真实的值,或者获取子元素的类型

这里着重讲一下Elem的注意点

官方文档中写道

// 返回内部子元素类型,只能由类型 Array, Chan, Map, Ptr, or Slice 调用
Elem() Type

所以我们可以理解当使用reflect.Typeof(a).Elem()时,a只能放地址值,或组数组,Map,Slice一类的变量,如果我们的a是结构体的真值会panic

a := struct {
     
		Name string
		Age int
	}{
     
		Name: "haha",
		Age: 1,
	}
reflect.Typeof(a).Elem() //发生panic 因为reflect.Typeof(a)是struct
reflect.Typeof(&a).Elem() //正确 因为reflect.Typeof(a)是ptr(地址类型) Elem获得的是一个结构体类型

还有一个很重要的点是,当传入reflect.Typeof(a).Elem()的a是一个数组,Slice或者Map时,获取到的是子元素的类型,reflect.Typeof(&a).Elem()获取的是a的类型

a := [4]int{1,1,1,1}
fmt.Print(reflect.TypeOf(&a).Elem(),reflect.TypeOf(a).Elem())
//输出  [4]int int

当使用reflect.Valueof(&a).Elem()是传入的必须是地址值,要不然会直接Panic

a := [4]int{
     1,1,1,1}
fmt.Print(reflect.ValueOf(a).Elem())
//Panic 必须传入地址值

只有使用了Elem()获取地址值的真实值才能对原始值进行修改操作

你可能感兴趣的:(go,go,golang,reflect,反射)