反射(reflect)
是Go语言提供的动态获取对象类型及结构信息的方式。
Go语言中的反射可以帮助处理未知类型,但是使用次数非常少。
反射的包为 reflect包:包含两个核心类型: reflect.Value 和 reflect.Type。
前者用于存储任意值,后者用于存储任意类型。
一、反射的使用
x1 := X{A1:100,B1:3.14,C1:true}
y1 := Y{A2:1,B2:2,C2:1.5,D2:"hello"}
rx1 := reflect.ValueOf(&x1).Elem() // rx1: {100 3.14 true}
ry1 := reflect.ValueOf(&y1).Elem() // ry1: {1 2 1.5 hello}
定义了两个结构体: X
和Y
的变量x1
和y1
,通过reflect.ValueOf
方法获取新创建的变量的地址,一般该方法返回的是传入变量的一份值复制。
此处直接传递变量的地址,得到的也是变量的地址对象。然后调用Elem方法获取地址指针指向的值封装。
x1Type := rx1.Type()
y1Type := ry1.Type()
fmt.Println("x1Type: ",x1Type) // x1Type: main.X
fmt.Println("y1Type: ",y1Type) // y1Type: main.Y
通过调用Type方法可以获取变量的类型。
rx1.NumField()
NumField
方法返回 reflect.Value 结构中的字段个数。
二、反射的缺点
反射能实现动态获取对象类型,但是不建议经常使用,因为会导致代码自身的可读性较差。
反射代码的写法可读性比较差,不利于后续的运维。
反射的实现比较复杂,所以反射执行得比较慢,会影响程序的整体性能。
反射的错误在编译时无法发现,到运行时才报错,而且都是panic类型,这容易让程序崩溃。