Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you create a new instance of a struct from its type at run time in Go?

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.

like image 911
Mat Ryer Avatar asked Oct 21 '11 13:10

Mat Ryer


People also ask

Which is the correct way to create an instance of struct type?

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.

How do I create a struct object in Golang?

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.

How do you create a structure in go?

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.

Can we create instance of structure?

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.


2 Answers

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.

like image 181
Evan Shaw Avatar answered Oct 13 '22 01:10

Evan Shaw


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()) } 
like image 31
Sridhar Ratnakumar Avatar answered Oct 12 '22 23:10

Sridhar Ratnakumar