Go - reflection
Go 语言也有反射的机制,通过这种机制可以大大提高程序的灵活性。
reflect包中的 TypeOf 与 ValueOf 方法
首先,当我们想要使用反射技术的时候,我们需要先引用 reflect 包。
import ( "fmt" "reflect" )
之后,我们就可以通过reflect包中的TypeOf方法来取到类型,并且使用ValueOf方法来获取字段及方法。我们来看一个实例
// reflect.go package main import ( "fmt" "reflect" ) type User struct { Name string Age int Sex string } func (u User) SayHello() { fmt.Println("Hello there, I am %s ...", u.Name) } func main() { user := User{ "Tony", 30, "male"} info(user) } func info(o interface{}) { t := reflect.TypeOf(o) fmt.Printf("Type is: %s \n", t.Name()) fmt.Printf("Fields are: \n") // find out fileds v := reflect.ValueOf(o) 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) } // find out methods for i := 0; i < t.NumMethod(); i++ { m := t.Method(i) fmt.Printf("%6s: %v\n", m.Name, m.Type) } }
output:
使用反射修改类型
如果我们需要通过反射的方式来修改类型的字段,那么传入给ValueOf()方法的参数应该是对象的引用。
// reflect1.go package main import ( "fmt" "reflect" ) type People struct { Name string Age int } func main() { p := People{"Tony", 30} fmt.Printf("my name is: %s\n", p.Name) val := reflect.ValueOf(&p) f := val.Elem().FieldByName("Name") f.SetString("Tom") fmt.Printf("my name is: %s\n", p.Name) }
使用反射来“动态”调用方法
// reflect1.go package main import ( "fmt" "reflect" ) type People struct { Name string Age int } func (p People) Hello(name string) { fmt.Printf("Hello there, I am %s", name) } func main() { p := People{"Tony", 30} v := reflect.ValueOf(p) mv := v.MethodByName("Hello") args := []reflect.Value{reflect.ValueOf("Tom")} mv.Call(args) }
需要注意的是,通过反射调用方法的时候需要以slice的形式传入参数,
args := []reflect.Value{reflect.ValueOf("Tom")}
最后使用method.call来调用方法
mv.Call(args)