Go反射机制:在编译不知道类型的情况下,可更新变量、在运行时查看值、调用方法以及直接对它们的布局进行操作。
为什么使用反射
有时需要封装统一接口对不同类型数据做处理,而这些类型可能无法共享同一个接口,也有可能布局未知,也有可能该类型在程序设计时不存在。
当无法透视一个未知类型的布局时,这段代码就无法继续,所以引入反射机制。
reflect.Type与reflect.Value
Golang反射机制提供两种类型:Type和Value。
Type是一个接口,其中提供很多方法,能够识别类型以及透视类型的组成部分。Value可以包含一个任意类型的值。
reflect.TypeOf
TypeOf函数可以接受任何的interface{}参数,并且把接口中的动态类型以reflect.Type形式返回。TypeOf返回的是实际类型而非接口类型。例如:
var w io.Writer = os.Stdout
fmt.Println(reflect.TypeOf(w)) // os.File
reflect.ValueOf
ValueOf函数接受任意的interface{}并将接口的动态值以reflect.Value的形式返回。
type User struct {
Name string
Age int
} u := User{"Mike", 32}
v := reflect.ValueOf(u)
fmt.Println(v) // {Mike, 32}
reflect.Type
Type常用方法整理如下:
-
Kind() Kind 获取底层类型
var w io.Writer = os.Stdout
fmt.Println(reflect.TypeOf(w)) // os.File
fmt.Println(reflect.TypeOf(w).Kind()) // struct NumField() int 获取结构类型的字段数量,可用于遍历结构
-
Field(i int) StructField 通过下标i获得某一字段项
type User struct {
Name string
Age int
} u := User{"Mike", 32}
t := reflect.TypeOf(u) for i := 0; i < t.NumField(); i++ {
fmt.Println(t.Field(i).Name)
} -
NumMethod() 获得类型的方法集中被导出方法的数量
for i := 0; i < t.NumMethod(); i++ {
fmt.Println(t.Method(i).Name)
}
reflect.Value
Value常用方法整理如下:
-
func (v Value) Interface() (i interface{}) 以 interface{} 形式返回v的当前值
type User struct {
Name string
Age int
} u := User{"Mike", 32}
v := reflect.ValueOf(u)
fmt.Println(v.Interface.(User)) // {Mike, 32} -
func (v Value) Kind() Kind 返回v的底层类型
fmt.Println(v.Kind()) // struct