注意:反射获取字段给字段赋值时,该字段必须首字母大写,否则会引起恐慌报如下错误:
panic: reflect: reflect.flag.mustBeAssignable using value obtained using unexported field
1.变量结构
type,value(pair)
2.reflect包
1.reflect类型
const (
Invalid Kind = iota //0~26
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 //26
)
2.获取kind
package main
import "reflect"
type User struct {
Name string
Age int
}
func refTest(arg interface{}) {
var argType reflect.Type = reflect.TypeOf(arg)
var argValue reflect.Value = reflect.ValueOf(arg)
print(argType.Kind())
print(argValue.Kind())
}
func main() {
refTest(User{"zhangsna", 11})
//25 struct类型
}
3.获取属性
package main
import (
"fmt"
"reflect"
)
type User struct {
//定义字段,并设置字段标签
Name string `info:"名字" doc:"哈哈"`
Age int `info:"年龄"`
height float64 `info:"身高"`
}
func (user *User) GetName() string {
return user.Name
}
//interface{}是万能数据类型
func myFunc(arg interface{}) {
//通过参数获取,参数的类型和值
argType := reflect.TypeOf(arg)
argValue := reflect.ValueOf(arg)
//当arg是pir时,需要通过argType.Elem()获取属性,例如argType.Elem().NumField()
for i := 0; i < argType.NumField(); i++ {
//通过type获取内部字段类型和值
field := argType.Field(i)
value := argValue.Field(i)
fmt.Println(field.Name, field.Type, value)
//获取字段标签,Tag只存在类型里
info := argType.Field(i).Tag.Get("info")
doc := argType.Field(i).Tag.Get("doc")
fmt.Println("标签info为:", info, "doc为", doc)
}
//通过type获取内部方法,只能获取非地址传值的方法
for i := 0; i < argType.NumMethod(); i++ {
method := argType.Method(i)
fmt.Println(method.Name, method.Type)
}
}
func main() {
user := User{"张三", 24, 1.70}
myFunc(user)
}
4.反射修改值
package main
import (
"fmt"
"reflect"
)
func refTest(arg interface{}) {
argValue := reflect.ValueOf(arg)
argValue.Elem().SetInt(10)
}
func main() {
var a int = 11
//必须传递指针
refTest(&a)
fmt.Println(a)
}
5.反射调用方法