反射reflect包
反射的定义
反射可以对一个已知变量,可以动态的获得当前变量的type和value。
reflect.valueOf接口
valueOf用来获取输入参数接口中的数据的值。如果接口为空则返回0
// ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero Value.
func ValueOf(i interface{}) Value {
if i == nil {
return Value{}
}
// TODO: Maybe allow contents of a Value to live on the stack.
// For now we make the contents always escape to the heap. It
// makes life easier in a few places (see chanrecv/mapassign
// comment below).
escapes(i)
return unpackEface(i)
}
reflect.typeOf接口
typeOf用来动态获取输入参数接口中的值的数据类型,如果接口为空则返回nil。
// 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 {
eface := *(*emptyInterface)(unsafe.Pointer(&i))
return toType(eface.typ)
}
例题1:使用reflect获取简单变量的pair
package main
import (
"fmt"
"reflect"
)
// 该函数使用reflect包将传入的变量的type和value打印出来
func reflectNum(arg interface{}) {
fmt.Println("type: ", reflect.TypeOf(arg)) // 使用reflect包,打印出传递过来的变量的数据类型
fmt.Println("value: ", reflect.ValueOf(arg)) // 使用reflect包,打印出传递过来的变量的值
}
func main() {
var num float64 = 1.2345 // 声明一个浮点变量
reflectNum(num) // 调用函数
}
运行结果:
例题2:使用reflect获取复杂数据类型的变量的pair
reflect获取结构体的数据类型和值
package main
import (
"fmt"
"reflect"
)
type User struct {
Id int
Name string
Age int
}
func (this *User) Call() {
fmt.Println("user is called ..")
fmt.Printf("%v\n", this) // 打印变量的默认格式
}
func DoFiledAndMethod(input interface{}) {
// 获取input的type
inputType := reflect.TypeOf(input)
// 获取Name属性所在的结构体名
fmt.Println("inputType is :", inputType.Name())
// 获取input的value
inputValue := reflect.ValueOf(input)
// 打印获取到的input的真实值
fmt.Println("inputValue is:", inputValue)
}
func main() {
user := User{1, "peiqi", 18} // 实例化一个结构体
DoFiledAndMethod(user) // 调用函数
}
运行结果:
可以看到通过reflect可以获得到结构体的Type以及结构体的Value
reflect获取结构体所绑定的方法和方法对应的类型
获取思路如下:
- 获取interface的reflect.Type,通过Type得到numField(结构体内的属性称为numfield),进行遍历
- 得到每一个field(结构体的每一个属性称为一个field),获得数据类型
- 通过field有一个interface()方法得到对应的value
package main
import (
"fmt"
"reflect"
)
type User struct {
Id int
Name string
Age int
}
func (this User) Call() {
fmt.Println("user is called ..")
fmt.Printf("%v\n", this) // 打印变量的默认格式
}
func DoFieldAndMethod(input interface{}) {
// 获取input的type
inputType := reflect.TypeOf(input)
fmt.Println("inputType is :", inputType.Name())
// 获取input的value
inputValue := reflect.ValueOf(input)
fmt.Println("inputValue is:", inputValue)
// 通过type 获取里面的方法,调用
for i := 0; i < inputType.NumMethod(); i++ {
m := inputType.Method(i)
fmt.Printf("%s: %v\n", m.Name, m.Type)
}
}
func main() {
user := User{1, "peiqi", 18} // 实例化一个结构体
DoFieldAndMethod(user) // 调用函数
}
运行结果:
可以看到通过反射,可以获得实例对象的方法名和方法对应的类型。
详细反射接口可以多看看官方文档。
此处评论已关闭