In Go, how do you create the instance of an object from its type at run time? I suppose you would also need to get the actual type
of the object first too?
I am trying to do lazy instantiation to save memory.
Struct Instantiation Using new Keyword An instance of a struct can also be created with the new keyword. It is then possible to assign data values to the data fields using dot notation.
2 ways to create and initialize a new structThe new keyword can be used to create a new struct. It returns a pointer to the newly created struct. You can also create and initialize a struct with a struct literal. An element list that contains keys does not need to have an element for each struct field.
It is followed by the name of the type (Address) and the keyword struct to illustrate that we're defining a struct. The struct contains a list of various fields inside the curly braces. Each field has a name and a type. The above code creates a variable of a type Address which is by default set to zero.
A struct object can be created with or without the new operator, same as primitive type variables. Above, an object of the Coordinate structure is created using the new keyword.
In order to do that you need reflect
.
package main import ( "fmt" "reflect" ) func main() { // one way is to have a value of the type you want already a := 1 // reflect.New works kind of like the built-in function new // We'll get a reflected pointer to a new int value intPtr := reflect.New(reflect.TypeOf(a)) // Just to prove it b := intPtr.Elem().Interface().(int) // Prints 0 fmt.Println(b) // We can also use reflect.New without having a value of the type var nilInt *int intType := reflect.TypeOf(nilInt).Elem() intPtr2 := reflect.New(intType) // Same as above c := intPtr2.Elem().Interface().(int) // Prints 0 again fmt.Println(c) }
You can do the same thing with a struct type instead of an int. Or anything else, really. Just be sure to know the distinction between new and make when it comes to map and slice types.
As reflect.New
doesn't automatically make reference types used in struct fields, you could use something like the following to recursively initialize those field types (note the recursive struct definition in this example):
package main import ( "fmt" "reflect" ) type Config struct { Name string Meta struct { Desc string Properties map[string]string Users []string } } func initializeStruct(t reflect.Type, v reflect.Value) { for i := 0; i < v.NumField(); i++ { f := v.Field(i) ft := t.Field(i) switch ft.Type.Kind() { case reflect.Map: f.Set(reflect.MakeMap(ft.Type)) case reflect.Slice: f.Set(reflect.MakeSlice(ft.Type, 0, 0)) case reflect.Chan: f.Set(reflect.MakeChan(ft.Type, 0)) case reflect.Struct: initializeStruct(ft.Type, f) case reflect.Ptr: fv := reflect.New(ft.Type.Elem()) initializeStruct(ft.Type.Elem(), fv.Elem()) f.Set(fv) default: } } } func main() { t := reflect.TypeOf(Config{}) v := reflect.New(t) initializeStruct(t, v.Elem()) c := v.Interface().(*Config) c.Meta.Properties["color"] = "red" // map was already made! c.Meta.Users = append(c.Meta.Users, "srid") // so was the slice. fmt.Println(v.Interface()) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With