go语言:反射,用字符串调用函数创建结构 go语言可以通过反射来进行函数调用和类的创建,但是go中没有类型工厂,所以在使用前要“丑陋”的先把类型注册一下。 相关示例代码如下(未容错,仅做为示例,不能直接用于产品): 先看用法,免得被吓跑 ```go package main import ( "fmt" "utils/typefac" ) //测试调用 func main() { // 测试创建对象 typefac.RegisterType(HuaweiSchool{}) classinfo := "main.HuaweiSchool" in := make(map[string]interface{}) in["Name"] = &StcName{"Euler1"} in["Id"] = 111 school := typefac.CreateInstance(classinfo, in).(School) fmt.Println(school) school.PrintName() school.SetID(222) school.PrintName() // 测试调用函数 typefac.RegFunc("NewHuaweiSchool", NewHuaweiSchool) v, _ := typefac.Run("NewHuaweiSchool", "Euler2", 123) school = v[0].Interface().(*HuaweiSchool) school.PrintName() } type School interface { PrintName() SetID(int) } type HuaweiSchool struct { Name *StcName Id int } func (s HuaweiSchool) PrintName() { fmt.Println("welcome to huawei", s.Name, " school, id:", s.Id) } func (s *HuaweiSchool) SetID(id int) { s.Id = id } type StcName struct { Name string } func NewHuaweiSchool(name string, id int) *HuaweiSchool { m := new(HuaweiSchool) m.Name = &StcName{name} m.Id = id return m } ``` 相关库 ```go package typefac import ( "errors" "reflect" ) var funcMap = make(map[string]interface{}) // RegFunc 注册一个函数 // typefac.RegFunc("NewHuaweiSchool", NewHuaweiSchool) func RegFunc(name string, fc interface{}) { funcMap[name] = fc } // Run 运行被注册的函数 // usage: v, _ := typefac.Run("NewHuaweiSchool", "Euler2", 123) // school = v[0].Interface().(*HuaweiSchool) func Run(name string, params ...interface{}) (result []reflect.Value, err error) { if _, ok := funcMap[name]; !ok { err = errors.New(name + " does not exist.") return } f := reflect.ValueOf(funcMap[name]) if len(params) != f.Type().NumIn() { err = errors.New("The number of params is not adapted") return } in := make([]reflect.Value, len(params)) for k, param := range params { in[k] = reflect.ValueOf(param) } result = f.Call(in) return } var typeRegistry = make(map[string]reflect.Type) // RegisterType 注册类型 func RegisterType(typedNil interface{}) { t := reflect.TypeOf(typedNil) typeRegistry[t.PkgPath()+"."+t.Name()] = t } // CreateInstance 传入被注册的类型和初值,创建一个对象 // usage: in := make(map[string]interface{}) // in["Name"] = StcName{"Euler1"} // in["Id"] = 111 // school := typefac.CreateInstance(classinfo, in).(School) func CreateInstance(name string, input map[string]interface{}) interface{} { structObj := reflect.New(typeRegistry[name]) structObjValue := structObj.Elem() for attrname, attrvalue := range input { // structObjValue.FieldByName(attrname).Set(reflect.ValueOf(attrvalue)) assign(structObjValue.FieldByName(attrname), attrvalue) } return structObj.Interface() } func assign(v reflect.Value, input interface{}) { iv := reflect.ValueOf(input) if v.CanSet() { switch v.Kind() { case reflect.Bool: v.SetBool(iv.Bool()) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: v.SetInt(iv.Int()) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: v.SetUint(iv.Uint()) case reflect.String: v.SetString(iv.String()) case reflect.Slice: //TODO... case reflect.Map: //TODO... case reflect.Struct: for i := 0; i < v.NumField(); i++ { structAttr := v.Field(i) if structAttr.IsValid() == false || structAttr.CanSet() == false { continue } assign(structAttr, iv.Field(i).Interface()) } case reflect.Ptr: v.Set(iv) } } } ``` 来自 大脸猫 写于 2015-11-05 20:29 -- 更新于2020-10-19 13:06 -- 2 条评论