lifelong learning & practice makes perfect
reflect包让Go程序具备运行时的反射能力(reflection)。反射是程序在运行时访问、检测和修改它本身状态或行为的一种能力
经由接口(interface{})类型变量值进入反射的世界并获得对应的反射对象(reflect.Value或reflect.Type)。
通过reflect.TypeOf可以得到reflect.Type包含实例的全部类型信息
可以得到reflect.Value(包含实例的值信息,还可用过Type方法获取类型信息,样例)
反射对象(reflect.Value)通过化身为一个接口(interface{})类型变量值的形式走出反射世界。 reflect.Value.Interface()是reflect.ValueOf()的逆过程,通过Interface方法我们可以将reflect.Value对象恢复成一个interface{}类型的变量值
func main() {
var i = 5
val := reflect.ValueOf(i)
r := val.Interface().(int)
fmt.Println(r) // 5
r = 6
fmt.Println(i, r) // 5 6
val = reflect.ValueOf(&i)
q := val.Interface().(*int)
fmt.Printf("%p, %p, %d\n", &i, q, *q) // 0xc0000b4008, 0xc0000b4008, 5
*q = 7
fmt.Println(i) // 7
}
反射对象对应的reflect.Value必须是可设置的(Settable) 当被反射对象以值类型(T)传递给reflect.ValueOf时,在反射世界中对反射对象值信息的修改不会对被反射对象产生影响。Go的设计者们认为这种修改毫无意义,并禁止了这种行为(panic)
var i = 17
val := reflect.ValueOf(i)
val.SetInt(27) // panic: reflect: reflect.flag.mustBeAssignable using unaddressable value
reflect.Value提供了CanSet、CanAddr及CanInterface等方法来帮助我们判断反射对象是否可设置(Settable)、可寻址、可恢复为一个interface{}类型变量