How to new an object with string in Golang

前端 未结 2 1025
忘掉有多难
忘掉有多难 2021-01-25 11:25

How can I create an object when I am only having its type in string? I am looking for something like:

type someStruct struct {}

resultObject := new \"someStruct         


        
相关标签:
2条回答
  • 2021-01-25 11:44

    No...

    Well, the answer is "yes, but" and it's a big but. There's no central registry of struct names in Go. You're not going to get a nice, clean standard library function called StructFromName(string) which is probably what you were hoping for.

    Instead, you have to write that mapping yourself, something like

    func StringToStruct(name string) (interface{}, error) {
        switch name {
        case "SomeStruct":
            return SomeStruct{}, nil
        case "SomeOtherStruct":
            return SomeOtherStruct{}, nil
        case "subpackage.Struct":
            return subpackage.Struct{}, nil
        default:
            return nil, fmt.Errorf("%s is not a known struct name", name)
        }
    }
    
    0 讨论(0)
  • 2021-01-25 11:54

    You can't directly do that in Go. The only thing close to that Go supports is reflect.New() in the reflection library, which accepts a reflect.Type object and creates a new value of its type.

    Now, if you'd like to initialize a type instance by name, you can build a registry of types by name, and have a function that looks up the type by name and creates an instance. It's really ugly though and not very idiomatic to Go, but it can be done.

    [EDIT] here's a working example of this. You still need to do type conversion manually:

    package main
    
    import (
        "fmt"
        "reflect"
    )
    
    //just a couple of structs
    type Foo struct {
        Lol string
    }
    
    type Bar struct {
        Wut string
    }
    
    
    //this is the registry of types by name
    var registry = map[string]reflect.Type{}
    
    // add a type to the registry
    func registerType(t reflect.Type) {
        name := t.Name()
        registry[name] = t
    }
    
    
    // create a new object by name, returning it as interface{}
    func newByName(name string) interface{} {
    
        t, found := registry[name]
        if !found {
            panic("name not found!")
        }
    
        return reflect.New(t).Elem().Interface()
    }
    
    func main() {
    
        //register foo and bar
        registerType(reflect.TypeOf(Foo{}))
        registerType(reflect.TypeOf(Bar{}))
    
        //create new instances
        foo := newByName("Foo").(Foo)
        bar := newByName("Bar").(Bar)
    
        fmt.Println(reflect.TypeOf(foo), reflect.TypeOf(bar))
    }
    

    And again, I wouldn't advise you to do this, it's ugly and slow and non idiomatic

    0 讨论(0)
提交回复
热议问题