golang 反射 reflect demo
< 返回列表时间: 2020-06-29来源:OSCHINA
package main import ( "fmt" "go/ast" "reflect" ) type Member struct { Id int `json:"id" orm:"member_id"` Name string `json:"name"` status bool } func (m *Member) SetStatus(s bool) { m.status = s } func (m *Member) GetStatus() bool { return m.status } func (m Member) String() string { return fmt.Sprintf("id: %d, name: %s", m.Id, m.Name) } // 如果是值传递那么反射获取的对象将不能修改此值,否则 panic func Parse(v interface{}) { // 获取 v 的变量值,如果是地址传递获取的是指针,值传递则为变量值 rValue := reflect.ValueOf(v) // 判断是否为一个指针,如果是指针就通过 Elem() 获取指针指向的变量值 rValue = reflect.Indirect(rValue) // 获取 v 的变量类型 rType := rValue.Type() // rType := reflect.TypeOf(v) switch rType.Kind() { case reflect.Struct: // 遍历结构体字段 for i := 0; i < rValue.NumField(); i++ { field := rType.Field(i) // 忽略匿名字段和私有字段 if !field.Anonymous && ast.IsExported(field.Name) { // 获取结构体字段的 interface{} 变量 fmt.Println(rValue.Field(i).Interface()) // 对于值传递的结构体使用 Addr() 获取结构体字段 *interface{} 变量会报错 fmt.Println(reflect.TypeOf(rValue.Field(i).Addr().Interface())) // 获取字段 tag fmt.Println(rType.Field(i).Tag.Get("json")) } } // 根据字段名获取字段 interface{} fmt.Println(rValue.FieldByName("Name").Interface()) // 获取非指针方法数量,案例中的 Member 的 String 方法 fmt.Println(rValue.NumMethod()) // 获取所有方法数量 fmt.Println(rValue.Addr().NumMethod()) // 遍历结构体方法 rValue.Addr().MethodByName("SetStatus").Call([]reflect.Value{reflect.ValueOf(true)}) fmt.Println(rValue.Addr().MethodByName("GetStatus").Call(nil)) // 排序默认是按照函数名的排序(ASCII 码) fmt.Println(rValue.Addr().Method(2).Call(nil)) fmt.Println(rValue.Method(0).Call(nil)) // 创建一个新反射对象 fmt.Println(reflect.New(rType).Elem().FieldByName("Id")) case reflect.Func: num := 2 argv := make([]reflect.Value, rType.NumIn()) for i := range argv { if rType.In(i).Kind() == reflect.Int { argv[i] = reflect.ValueOf(num) } } result := rValue.Call(argv) if len(result) == 1 { fmt.Println(result[0].Int()) } case reflect.Int: // 修改值 rValue.SetInt(127) // 从反射对象获取 interface{} 变量 rIntf := rValue.Interface() // 根据 interface{} 进行类型断言 if num, ok := rIntf.(*int); ok { fmt.Println(num) } case reflect.Slice: // 切片类型 fmt.Println(rType.Kind()) // 切片内元素类型 // Elem() 作用是返回接口 v 包含的值或 v 指向的指针 fmt.Println(rType.Elem().Kind()) } } func Add(a, b int) int { return a + b } func main() { m := &Member{ Id: 23, Name: "jack", } Parse(m) fmt.Println(m.GetStatus()) // 函数调用 Parse(Add) num := 6 // 如果为值传递修改时会 panic Parse(&num) fmt.Println(num) var ms []Member Parse(&ms) } /* 23 *int id jack *string name jack 1 3 [<bool Value>] [id: 23, name: jack] [id: 23, name: jack] 0 true 4 127 slice struct */
热门排行