golang之reflect
reflect,反射。
利用reflect,可以得到一个struct的相关信息。
package main import ( "fmt" "reflect" ) type User struct { Id int Name string Age int } func (u User) Hello(name string) { fmt.Printf("hello %s, my name is %s\n", name, u.Name) } type Manager struct { User title string } func main() { // modify variable through reflect //x := 123 //v := reflect.ValueOf(&x) //v.Elem().SetInt(234) //fmt.Println(x) u := User{1, "xiaoming", 12} u.Hello("atom") // call method through reflect v := reflect.ValueOf(u) mv := v.MethodByName("Hello") args := []reflect.Value{reflect.ValueOf("jack")} mv.Call(args) Info(u) Set(&u) Info(u) m := Manager{User{1, "xiaoming", 12}, "rd"} // get nested struct field t := reflect.TypeOf(m) fmt.Printf("%#v\n", t.Field(0)) fmt.Printf("%#v\n", t.FieldByIndex([]int{0,0})) } func Info(i interface{}) { t := reflect.TypeOf(i) if t.Kind() != reflect.Struct { fmt.Println("Type Error") return } fmt.Println("Type:", t.Name()) v := reflect.ValueOf(i) // get fields fmt.Println("Fields:") for i := 0; i < t.NumField(); i++ { f := t.Field(i) val := v.Field(i).Interface() fmt.Printf("%6s: %v = %v\n", f.Name, f.Type, val) } // get methods fmt.Println("Methods:") for i := 0; i < t.NumMethod(); i++ { m := t.Method(i) fmt.Printf("%6s: %v\n", m.Name, m.Type) } } func Set(i interface{}) { v := reflect.ValueOf(i) if v.Kind() != reflect.Ptr || !v.Elem().CanSet() { fmt.Println("Error") return } else { v = v.Elem() } f := v.FieldByName("Name") if !f.IsValid() { fmt.Println("Bad Field") } if f.Kind() == reflect.String { f.SetString("byebye") } }
输出如下:
hello atom, my name is xiaoming
hello jack, my name is xiaoming
Type: User
Fields:
Id: int = 1
Name: string = xiaoming
Age: int = 12
Methods:
Hello: func(main.User, string)
Type: User
Fields:
Id: int = 1
Name: string = byebye
Age: int = 12
Methods:
Hello: func(main.User, string)
reflect.StructField{Name:"User", PkgPath:"", Type:(*reflect.rtype)(0x10d9e00), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:true}
reflect.StructField{Name:"Id", PkgPath:"", Type:(*reflect.rtype)(0x10c4e60), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:false}
需要注意的一个地方是:
结构体的field首字母需要大写,否则会报错"panic: reflect.Value.Interface: cannot return value obtained from unexported field or method"
参考资料