Go 的反射

来源:互联网 发布:电脑怎么检查网络 编辑:程序博客网 时间:2024/06/01 07:30

Go 的反射reflection


1.反射可以大大提升程序的灵活性,使得interface{}有更大的发挥余地
2.反射使用TypeOf和ValueOf函数从接口中获得目标对象的信息
3.反射会将匿名字段作为独立的字段
4.想要利用反射修改对象的状态,前提是interface.data是settable,即pointer-interface
5.通过反射可以动态的调用方法

以下举个例子

package mainimport ("fmt""reflect")type User struct {Id   intName stringAge  int}func (u User) Hello() {fmt.Println("Hello,",u.Name)}func main() {u := User{1, "Jack", 14}Info(u)}func Info(o interface{}){t := reflect.TypeOf(o)fmt.Println("Type:",t.Name())v := reflect.ValueOf(o)fmt.Println("Fields:",v)//取得字段信息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)}//取得方法信息for i :=0;i <t.NumMethod();i++{m :=t.Method(i)fmt.Printf("%6s: %v\n",m.Name,m.Type)}}


输出的结果是
Type: UserFields: {1 Jack 14}    Id: int = 1   Name: string = Jack    Age: int = 14  Hello: func(main.User)

通过反射修改目标对象


package mainimport ("fmt""reflect")func main() {x := 123v := reflect.ValueOf(&x)v.Elem().SetInt(999)fmt.Println(x)}

结果是 999

通过反射修改目标结构体内容

package mainimport ("fmt""reflect")type User struct {Id   intName stringAge  int}func main() {u := User{1,"Jack",12}Set(&u)fmt.Println("Name:",u.Name)}func Set(o interface{}) {v := reflect.ValueOf(o)if v.Kind() == reflect.Ptr && !v.Elem().CanSet(){fmt.Println("XXX")return}else{v = v.Elem()}f:=v.FieldByName("Name")if !f.IsValid(){fmt.Println("Bad")return}if f.Kind()==reflect.String{f.SetString("Tom")}}

修改之后Name从Jack改成了Tom


通过反射来调用方法


package mainimport ("fmt""reflect")type User struct {Id   intName stringAge  int}func (u User) Hello(name string){fmt.Println("Hello,",name,".my name is ",u.Name)}func main() {u := User{1,"Jack",12}v := reflect.ValueOf(u)mv := v.MethodByName("Hello")args := []reflect.Value{reflect.ValueOf("Tom")}mv.Call(args)}

执行结果:
Hello, Tom .my name is  Jack