新手问题 golang 如何动态创建struct

astaxie · 2016年10月13日 · 最后由 Lampo 回复于 2017年08月25日 · 493 次阅读

如题: 如果我有一个 struct

type test struct{
    Name string
    Sex int
}

func main(){
    str := "tset" // 这里的test 可以是我在form 表单里面传递过来的一个数据
    obj := new(str) // 请问一下,有没有什么办法可以实现我这样的???
}
更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio

用 reflect 么?

静态语言貌似不能直接实现 可以自己实现个 map[string] func(string) interface{} 将要动态生成的结构体的函数注册上去 通过 string 来调用相应的函数来获取对应的结构体

var obj interface{}

switch ...{
    case "test":
        obj = test{}
    case "test2":
        obj = test2{}
    default:
        fmt.Println("mismatched.")

}

这样吧,既可以过滤表单输入,也可以达到 “动态” 创建的效果。

go 语言没有提供根据类型名称返回类型变量的功能,但是你可以通过设置一个:

var typemap = make(map[string]reflect.Type)

然后把你的结构体注册到这个表中,之后你可以通过这个表通过类型名获取类型,之后用反射创建对象就行了。

感觉应该是用 reflect 来解决, 但是 reflect 动态生成,得知道类型,reflect.Type. reflect.New(type) 可以动态生成一个 reflect.Value。 得到 value 了就可以用接口来转换了

func New(typ Type) Value New returns a Value representing a pointer to a new zero value for the specified type. That is, the returned Value's Type is PtrTo(typ).

Go Playground

package main

import (
    "fmt"
    "reflect"
)

var typeRegistry = make(map[string]reflect.Type)

func registerType(elem interface{}) {
    t := reflect.TypeOf(elem).Elem()
    typeRegistry[t.Name()] = t
}

func newStruct(name string) (interface{}, bool) {
    elem, ok := typeRegistry[name]
    if !ok {
        return nil, false
    }
    return reflect.New(elem).Elem().Interface(), true
}

func init() {
    registerType((*test)(nil))
}

type test struct {
    Name string
    Sex  int
}

func main() {
    structName := "test"

    s, ok := newStruct(structName)
    if !ok {
        return
    }

    fmt.Println(s, reflect.TypeOf(s))

    t, ok := s.(test)
    if !ok {
        return
    }
    t.Name = "i am test"
    fmt.Println(t, reflect.TypeOf(t))
}

t := test{} json.Unmarshal(bytes, &t)

前提是 bytes 是和这个结构相符的 json 字符串

尽量不要使用反射,性能不好而且会比较复杂

可不可以, 先生成对象池, 然后根据传递的名称去对象池中取对象呢?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册