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
}
相关库
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)
}
}
}