- golang的反射是通过reflect包来完成的,或者说是通过操作reflect包内的Type和Value两个结构体来完成的
Type
函数介绍
//TypeOf 返回一个以reflect.Type表示的i,这是使用类型反射的入口
reflect.TypeOf(i interface) Type
//Elem 返回接收者t内元素的Type
//注意:接收者t的Kind是Array Chan Map Ptr或Slice,其它类型会panic
func (t *rtype) Elem() Type
//Implements 返回接收者t是否实现了u所表示的Interface
func (t *rtype) Implements(u Type) bool
//Kind 返回接收者t的类型,有reflect.String、reflect.Struct、reflect.Ptr和reflect.Interface等
func (t *rtype) Kind() Kind
//NumFiled 返回接收者t表示的结构体内的字段数
//NumFiled 注意:接收者t的Kind必须是Struct,其它(包括结构体指针)会panic
func (t *rtype) NumFiled() int
//Filed 返回以StructField表示的接收者t表示的结构体内的第i个字段
//Filed 注意:接收者t的Kind必须是Struct,其它(包括结构体指针)会panic
func (t *rtype) Filed(i int) StructField
//NumMethod 返回接收者t的方法数
//NumMethod 注意方法的接收者是结构体还是结构体的指针
func (t *rtype) NumMethod() int
//Method 返回以Method表示的接收者t所表示的第i个方法
func (t *rtype) Method(i int) Method
//NumIn 返回接收者t所表示的函数的参数的数目
//NumIn 接收者t的Kind必须是Func,其它类型会panic
func (t *rtype) NumIn() int
//In 返回接收者t所表示的函数的第i个参数的Type
//In 接收者t的Kind必须是Func,其它类型会panic
func (t *rtype) In(i int) Type
//NumOut 返回接收者t所表示的函数的返回值的数目
//NumOut 接收者t的Kind必须是Func,其它类型会panic
func (t *rtype) NumOut() int
//Out 返回接收者t所表示的函数的第i个返回值的Type
//Out 接收者t的Kind必须是Func,其它类型会panic
func (t *rtype) Out(i int) Type
//StructField 截选部分
type StructField struct {
Name string // Name is the field name.
Type Type // field type
Tag StructTag // field tag string
Anonymous bool // is an embedded field
}
示例
type Person struct {
name string `default:"Bob"`
age int `default:"10"`
}
//自定义tag
p := Person{
name: "AcTarjan",
age: 22,
}
ptype := reflect.TypeOf(&p).Elem()
for i := 0;i < ptype.NumField();i++ {
field := ptype.Field(i)
val,ok := field.Tag.Lookup("default")
if ok {
fmt.Println(field.Name,val)
}
}
/*
运行结果:
name Bob
age 10
Value
函数介绍
//ValueOf 返回一个以reflect.Value表示的i,这是使用值反射的入口
reflect.ValueOf(i interface) Value
//Interface 返回Value的Interface{}表示,会重新分配内存,然后可以强转成某种类型
//Interface 注意:如果接收者是通过访问未导出字段获得的,将会panic
func (v value) Interface() (i interface{})
//Kind 返回接收者v的类型,有reflect.String、reflect.Struct、reflect.Ptr和reflect.Interface等
func (v Value) Kind() Kind
//Elem 如果接收者v的Kind是Ptr,该方法将返回一个以Value表示的该指针指向的结构体
//如果接收者v的Kind是Interface,该方法将返回一个以Value表示的Interface所包含的结构体
func (v Value) Elem() Value
//NumFiled 返回接收者v表示的结构体内的字段数
//NumFiled 注意:接收者v的Kind必须是reflect.Struct,其它(包括结构体指针)会panic
func (v Value) NumFiled() int
//Filed 返回以Value表示的接收者v表示的结构体内的第i个字段
//Filed 注意:接收者v的Kind必须是reflect.Struct,其它(包括结构体指针)会panic
func (v Value) Filed(i int) Value
//NumMethod 返回接收者v的方法数
//NumMethod 注意方法的接收者是结构体还是结构体的指针
func (v Value) NumMethod() int
//Method 返回以Value表示的接收者v表示的第i个方法
func (v Value) Method(i int) Value
//Call 调用接收者v所表示的函数,in为函数的参数
//Call 注意:接收者v的Kind必须是reflect.Func
func (v Value) Call(in []Value) []Value
//CanSet 返回接收者v的Value是否是可修改的,如果CanSet is false,调用Set方法会panic
//CanSet 注意:接收者必须是可寻址的(指针),且Set的字段为导出的
func (v Value) CanSet() bool
//SetString 修改接收者v的值,其中v的Kind必须是reflect.String,否则会panic
func (v Value) SetString(x string)
//String 返回接收者v的值,其中v的Kind要是reflect.String,其它则会返回"<T Value>",T为v的Kind
func (v Value) String() string
示例
type Person struct {
name string
age int
}
func (p *Person) Age() int {
return p.age
}
func (p *Person) SetAge(age int) {
p.age = age
}
//修改结构体字段的值
p := Person{
Name: "AcTarjan",
age: 22, //field age is unexported
}
val := reflect.ValueOf(&p).Elem()
field := val.FieldByName("Name")
field.SetString("Guo") //此时p = {"Guo",22}
fmt.Println(field.String()) //输出:Guo
//调用结构体的方法
p := Person{
Name: "AcTarjan",
age: 22,
}
val := reflect.ValueOf(&p)
method := val.MethodByName("SetAge")
in := []reflect.Value{reflect.ValueOf(30)}
method.Call(in) //此时p = {"AcTarjan",30}
method = val.MethodByName("Age")
fmt.Println(method.Call(nil)[0]) //输出:30