网站横条广告,中国建设银行官网招聘信息,营销型网站代理,甘肃省建设监理协会 官方网站概念
在Go语言中#xff0c;反射#xff08;reflection#xff09;是指在运行时检查程序的结构、变量和接口的机制。可以通过反射获取和修改变量的值、获取变量的类型信息、调用方法等操作。
反射主要由reflect包提供#xff0c;它定义了两个重要的类型#xff1a;Type和…概念
在Go语言中反射reflection是指在运行时检查程序的结构、变量和接口的机制。可以通过反射获取和修改变量的值、获取变量的类型信息、调用方法等操作。
反射主要由reflect包提供它定义了两个重要的类型Type和Value。Type代表一个Go类型的元数据Value则代表一个变量的值和类型信息。
通过反射可以动态地获取变量类型信息和值例如使用reflect.TypeOf()可以获取变量的类型使用reflect.ValueOf()可以获取变量的值。还可以使用Value提供的方法获取和设置变量的值、调用方法等。
需要注意的是反射操作相对较慢使用反射会带来一定的性能损失。因此应尽量避免过度使用反射谨慎地选择使用反射机制。
// ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero
func ValueOf(i interface{}) Value {...}翻译一下ValueOf用来获取输入参数接口中的数据的值如果接口为空则返回0// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
func TypeOf(i interface{}) Type {...}翻译一下TypeOf用来动态获取输入参数接口中的值的类型如果接口为空则返回nil
例子
执行reflect的两个接口
func main() {var num float64 1.2345fmt.Println(type: , reflect.TypeOf(num))fmt.Println(value: , reflect.ValueOf(num))// type: float64// value: 1.2345}针对reflect的两个接口返回值进一步探索
package mainimport (fmtreflect
)type User struct {Id intName stringAge int
}func (u User) ReflectCallFunc() {fmt.Println(Allen.Wu ReflectCallFunc)
}
func main() {user : User{1, Allen.Wu, 25}DoFiledAndMethod(user)}// 通过接口来获取任意参数然后一一揭晓
func DoFiledAndMethod(input interface{}) {getType : reflect.TypeOf(input)fmt.Println(get Type is :, getType.Name())getValue : reflect.ValueOf(input)fmt.Println(get all Fields is:, getValue)// 获取方法字段// 1. 先获取interface的reflect.Type然后通过NumField进行遍历// 2. 再通过reflect.Type的Field获取其Field// 3. 最后通过Field的Interface()得到对应的valuefor i : 0; i getType.NumField(); i {field : getType.Field(i)value : getValue.Field(i).Interface()fmt.Printf(%s: %v %v\n, field.Name, field.Type, value)}// 获取方法// 1. 先获取interface的reflect.Type然后通过.NumMethod进行遍历for i : 0; i getType.NumMethod(); i {m : getType.Method(i)fmt.Printf(%s: %v\n, m.Name, m.Type)}
}
反射设置值
package mainimport (fmtreflect
)func main() {var num float64 1.2345fmt.Println(old value of pointer:, num)// 通过reflect.ValueOf获取num中的reflect.Value注意参数必须是指针才能修改其值pointer : reflect.ValueOf(num)newValue : pointer.Elem()fmt.Println(type of pointer:, newValue.Type())fmt.Println(settability of pointer:, newValue.CanSet())// 重新赋值newValue.SetFloat(77)fmt.Println(new value of pointer:, num)// 如果reflect.ValueOf的参数不是指针会如何pointer reflect.ValueOf(num)// newValue pointer.Elem() // 如果非指针这里直接panic“panic: reflect: call of reflect.Value.Elem on float64 Value”
}
reflect.Indirect()函数
package mainimport (fmtreflect
)type MyStruct struct {ID int
}func (s *MyStruct) DoSomething() {fmt.Println(Hello world)
}func main() {s : MyStruct{ID: 123}v : reflect.ValueOf(s) // v.Kind() is reflect.Ptrfmt.Println(v.Kind()) // ptrv1 : reflect.ValueOf(s).Elem() // v.Kind() is reflect.Ptrfmt.Println(v1.Kind()) // struct
}
显然v.Kind()的返回值是reflect.Ptr而不是MyStruct类型。这时我们可以使用reflect.Indirect()在反射中获取原始类型。
package mainimport (fmtreflect
)type Person struct {name stringage int
}func main() {p1 : Person{name: Alice, age: 30}v1 : reflect.ValueOf(p1)fmt.Println(v1.Kind():, v1.Kind())fmt.Println(v1.Type():, v1.Type())fmt.Println(v1.CanSet():, v1.CanSet())fmt.Println(v1.Elem().CanSet():, v1.Elem().CanSet())v1 reflect.Indirect(v1)fmt.Println(v1.Kind():, v1.Kind())fmt.Println(v1.Type():, v1.Type())fmt.Println(v1.CanSet():, v1.CanSet())//fmt.Println(v1.Elem().CanSet():, v1.Elem().CanSet())
}
输出 v1.Kind(): ptr v1.Type(): *main.Person v1.CanSet(): false v1.Elem().CanSet(): true v1.Kind(): struct v1.Type(): main.Person v1.CanSet(): true // panic: reflect: call of reflect.Value.Elem on struct Value