reflection
what is reflection
- Can be understood as inverse mapping
- Forward type, value —> object/variable
- reverse object/variable -> type, value
- Reflection is the way to obtain type information when the program is running
- Programmers can use these types of information for more flexible processing, such as:
- Let static languages have more diverse runtime dynamic features
- Let the program have introspection ability, so that the flexibility of the interface{} interface object has more room to play
- The go language provides a reflection package called reflect, which can:
- Get the Type and Value of the original object
- Modify the Value value of the original object
- Dynamically call the method of the original object
- ……
- The reflect package implements runtime reflection, allowing programs to manipulate objects of any type . Typical usage is to save a value with static type interface{}, and
TypeOf
obtain its dynamic type information by calling, and this function returns a Type type value. The callingValueOf
function returns a value of type Value, which represents the data at runtime. Zero takes a Type parameter and returns a Value representing the zero value of that type.
Related types and methods
func TypeOf
func TypeOf(i interface{}) Type
TypeOf
Returns the type of the value stored in the interface, TypeOf(nil)
will return nil.
type Type
type Type interface {
//Type 是一个接口
// Kind返回该接口的具体分类
Kind() Kind
// Name返回该类型在自身包内的类型名,如果是未命名类型会返回""
Name() string
// 返回struct类型的字段数(匿名字段算作一个字段),如非结构体类型将panic
NumField() int
// 返回struct类型的第i个字段的类型,如非结构体或者i不在[0, NumField())内将会panic
Field(i int) StructField
// 返回该类型的方法集中方法的数目
// 匿名字段的方法会被计算;主体类型的方法会屏蔽匿名字段的同名方法;
// 匿名字段导致的歧义方法会滤除
NumMethod() int
// 返回该类型方法集中的第i个方法,i不在[0, NumMethod())范围内时,将导致panic
// 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态
// 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil
Method(int) Method
/*
还有其他的方法,暂且省略
*/
}
Kind returns the specific category of the interface
Kind() Kind
func ValueOf
func ValueOf(i interface{
}) Value
ValueOf
Returns a Value initialized to the concrete value held by the i interface, ValueOf(nil)
returns Value zero.
type Value
type Value struct {
// 内含隐藏或非导出字段
}
The Value object has many methods, such as
func (Value)
func (v Value) Type() Type
Returns the Type representation of the type of the value held by v.
func (Value) Int
func (v Value) Int() int64
Returns the signed integer held by v (represented as int64
), if v's Kind is not Int、Int8、Int16、Int32、Int64
a panic
func (Value) Float
func (v Value) Float() float64
Returns the floating-point number held by v (expressed as float64
), if v's Kind is not Float32、Float64
a panic
func (Value) NumField
func (v Value) NumField() int
Returns the number of fields of the structure type value held by v, if the Kind of v is not Struct
a panic
func (Value) Field
func (v Value) Field(i int) Value
Returns the i-th field of the structure (the Value encapsulation). If the Kind of v is not Struct
or i is out of bounds, it will panic
func (Value) NumMethod
func (v Value) NumMethod() int
Returns the method number of the method set in which v holds a value.
func (Value) Method
func (v Value) Method(i int) Value
Returns a functional encapsulation of Value that is bound (to v's value-holding) state of the ith method of v's holding value type. The return value should not include a receiver when calling the Call method; functions held by the return value always use v's holder as the receiver (i.e., the first argument). If i is out of bounds, or the value held by v is the zero value (nil) of the interface type, it will panic.
func (Value) Interface
func (v Value) Interface() (i interface{})
This method returns the value currently held by v (expressed as/stored in the interface{} type), which is equivalent to:
var i interface{} = (v's underlying value)
If v is obtained by accessing a non-exported structure field, it will cause a panic.
type Kind
type Kind uint
Kind represents the specific classification represented by the value of the Type type. A value of zero indicates an illegal classification.
const (
Invalid Kind = iota
Bool
Int
Int8
Int16
Int32
Int64
Uint
Uint8
Uint16
Uint32
Uint64
Uintptr
Float32
Float64
Complex64
Complex128
Array
Chan
Func
Interface
Map
Ptr
Slice
String
Struct
UnsafePointer
)
type Method
type Method struct {
// Name是方法名。PkgPath是非导出字段的包路径,对导出字段该字段为""。
// 结合PkgPath和Name可以从方法集中指定一个方法。
// 参见http://golang.org/ref/spec#Uniqueness_of_identifiers
Name string
PkgPath string
Type Type // 方法类型
Func Value // 方法的值
Index int // 用于Type.Method的索引
}
example
Get the Type and Value of the original object
package main
import (
"fmt"
"reflect"
)
func main() {
pi := 3.1415
t := reflect.TypeOf(pi) //获取pi的类型信息
v := reflect.ValueOf(pi) //获取pi的值信息
if t.Kind() == reflect.Float64 {
fmt.Println("Type",t,"value", v.Float())//如果v不是float32或者float64会panic
}
}
Type float64 value 3.1415
compare type with kind
package main
import (
"fmt"
"reflect"
)
type people struct{
name string
age int
}
func main() {
pi := 3.1415
p :=people{
"kyl",18}
t := reflect.TypeOf(pi)
v := reflect.ValueOf(pi)
if t.Kind() == reflect.Float64 {
fmt.Println("Type",t,"value", v.Float(),"kind",v.Kind())
}
t=reflect.TypeOf(p)
v=reflect.ValueOf(p)
fmt.Println("Type",t,"value",v,"Kind",t.Kind())
}
Type float64 value 3.1415 kind float64
Type main.people value {kyl 18} Kind struct
It can be seen that type is not exactly the same as kind, especially in custom types
Get structure content and method information
package main
import (
"fmt"
"reflect"
)
type student struct {
ID int
Name string
Sex bool
Grade float32
}
func (s student) Myname() {
fmt.Println("my name is", s.Name)
}
func (s student) Sayhi() {
fmt.Println("hi nice to meet you!")
}
func structinfo(o interface{
}) {
//可以传入任何结构类型的对象
t := reflect.TypeOf(o)
if k := t.Kind(); k != reflect.Struct {
fmt.Println("not a struct")
return
}
fmt.Println("struct name is", t.Name())
fmt.Println("fields of struct is:")
v := reflect.ValueOf(o)
for i := 0; i < t.NumField(); i++ {
fmt.Println(t.Field(i).Type, ":", v.Field(i).Interface())
}
fmt.Println("Methods of struct is:")
for i:=0;i<t.NumMethod();i++{
fmt.Println(t.Method(i).Name,":",t.Method(i).Type,v.Method(i))//只能反射公有的方法
}
}
func main() {
stu := student{
1, "kyl", true, 96.5}
structinfo(stu)
}
struct name is student fields of struct is: int : 1 string : kyl bool : true float32 : 96.5 Methods of struct is: Myname : func(main.student) 0x48c4e0 Sayhi : func(main.student) 0x48c4e0