How to create a instance from string

type Todo struct 

is there a way to create a new Todo instance? like

func Create(funcName string) *Todo{
  //do something
}

Thanks.

Please specify a bit more. Do you want to return an instance of Todo? Then simply do return &Todo{}. But what’s the role of funcName then?

I want to dynamic create a struct instance by name.

type Todo struct
type Foo struct

func Create(name string) interface{}{
  //do something
}

func main(){
  todo := Create("Todo")
  foo := Create("Foo")
  //.....
}

This is pretty much never a good idea, why do you need to do this ?

I come from ruby, i want to dynamic call struct method by name, like callMethod("Todo.Hello"). it seems no way to do it… it seems that I should change my habits. Thanks.

You could use reflect, but the proper answer is indeed not to do this :slight_smile:

8 Likes

Will be somehow in the reflect package, using Type and Value. But never used it this way, only to get information about existing types.

Luna’s reply is on point.

I would add that trying to replicate the way you’re used to work in another language is never a good idea. Try to familiarize yourself with the Go way of doing things. In this case, by being explicit in what you want to call.

Effective Go is always a good recommendation while we’re on this subject.

2 Likes

Thanks, everyone.

Make sure not to search for a type/func/whatever by user input, and then calling that code. It would be a security risk.
If you process user input, I’d recommend to have a whitelist

factories := map[string]func() interface{} {
  "Todo": func() interface{} { return &Todo{} },
  "Foo":  func() interface{} { return &Foo{}  },
}

if f, ok := factories[name]; ok {
  x := f()
}
1 Like

This is still fairly bad practice, in all likelyhood if this is a http app, you just need to setup proper routing

3 Likes

@nyrf: i come from Ruby as well. Instead of just saying why “Go doesn’t do this,” I’ll provide some reasons:

  1. Go is strictly typed, and this is a very dynamic concept. The fact that Go is a strict type, compiled language helps with its speed compared to Ruby. Go is not meant to contain more Go code that is interpreted at runtime. It’s meant to be fully compiled.

  2. interface{} as a type should be a last resort, especially when defining new, primitive types. For instance, I’m sure you could find a create an interface that applies to both of your structs. 99% of the time, I can.

  3. This does not follow Go-idioms and will confuse fellow gophers. Instead, Go uses specific factory methods (ex. NewFoo() and NewTodo()). I begin to question the logic behind any library that attempts to circumvent this.

  4. Reflection is rarely the answer, because it is sometimes a maintenance nightmare. You should not need reflection for factories.

If you’d like further explanation about how to adapt your ideas, you can feel free to contact me. My email is on my github.

8 Likes

@codeblooded @Luna @nodir Thank you, seems use func name(rw http.ResponseWriter, req *http.Request) is the right way to build golfing web app.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.