zl程序教程

您现在的位置是:首页 >  后端

当前栏目

浅谈Go语言反射

2023-09-11 14:16:33 时间

1 为什么需要反射

反射是框架的灵魂。

反射(Reflection)其实是通过允许在运行时存取程序数据,以改变程序行为的程序设计技术。也就是说,反射可以帮助我们将动态的功能实现或调用变为静态的功能描述。

反射有优点就是可以让程序灵活,更新和维护都更加简单方便,但是反射并不是没有缺点,反射在执行时对于CPU和内存资源会进行占用。

2 Go反射的使用

2.1 针对结构体的反射

type Student struct {
   Id   int64
   Name string
   Age  int
}

func TestStruct(t *testing.T) {
	stu := Student{1, "zs", 12}
	obj := reflect.ValueOf(stu)
	field := obj.FieldByName("Name")
	field1 := obj.Field(0)
	num := obj.NumField()
	fmt.Println("字段数量:", num)
	fmt.Println("Name字段的值:", field)
	fmt.Println("第0个字段的值:", field1)
	obj1 := reflect.ValueOf(new(Student))
	addr := obj1.CanAddr() //是否能寻址
	if addr {
		fmt.Println(obj1.Addr())
	}
}

2.2 针对常见数据结构的反射

// 切片类型的反射
func TestSlice(t *testing.T) {
	slice := make([]int, 10)
	s := reflect.ValueOf(slice)
	//加入元素
	s.Index(0).Set(reflect.ValueOf(100))
	//获取元素
	i := s.Index(0).Interface()
	fmt.Println(slice)
	fmt.Println(i)
}

// Map类型的反射
func TestMap(t *testing.T) {
	m := make(map[string]interface{})
	m["A"] = 1
	m["B"] = 2
	m["C"] = 3
	mv := reflect.ValueOf(m)
	//赋值
	mv.SetMapIndex(reflect.ValueOf("D"),reflect.ValueOf(4))
	iter := mv.MapRange()
	keys := mv.MapKeys()
	fmt.Println(keys)
	for iter.Next() {
		fmt.Println(iter.Value())
	}
}

3 小总结

反射在架构中扮演者很重要的作用,其中最重要的就是增强架构的抽象,Go语言反射里最重要的两个概念是Type和Value,Type用于获取类型相关的信息(比如slice的长度,Struct的成员,函数的参数),Value用于获取和修改原始数据的值(比如修改slice和map中的元素,修改Struct的成员变量)。

参考:

https://zhuanlan.zhihu.com/p/411313885