I have a function that expects to receive an array of pointers to structs of unknown definitions. I want to be able to create a new instance of the unknown struct, assign values to it, and then append it to the given array.
// Someone using this package example:
type Foo Struct {
Val int
Nested []Bar
}
type Bar struct {
Val int
}
func main() {
var foos []*Foo
Mutate(&foos)
// Expect foos[0] to be:
// Foo{Val: 1, Nested: { Bar{Val: 2} } }
}
// My function (no access to definition of Foo)
func Mutate(target any) {
// This is where i am stuck
t := reflect.TypeOf(target).Elem()
// => []*main.Foo
// I have no idea of how to create a new instance
// of main.Foo or even see what fields it has.
}
Try this code:
func Mutate(target any) {
// Get reflect.Value for slice.
slice := reflect.ValueOf(target).Elem()
// Create pointer to value. Set a field in the value.
valuet := slice.Type().Elem().Elem()
valuep := reflect.New(valuet)
value := valuep.Elem()
value.FieldByName("Val").SetInt(1)
// Append value pointer to slice set resulting slice
// in target.
slice.Set(reflect.Append(slice, valuep))
}
https://play.golang.com/p/fAxkHexQheC
Jeremy Bender is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
0
While Jeremys answer goes in the right direction, the resulting foos[0]
is Foo{Val: 1, Nested: nil }
. Setting hierarchical values via reflect can be tricky, so may I suggest using JSON for this?
First generate an new Foo
value and append it to the slice:
t := reflect.ValueOf(target).Elem()
foo := reflect.New(t.Type().Elem().Elem())
t.Set(reflect.Append(t, foo))
then use JSON so fill in the value Foo{Val:1 Nested:[Bar{Val:2}]}
:
v := `{"Val":1,"Nested":[{"Val":2}]}`
if err := json.Unmarshal([]byte(v), foo.Interface()); err != nil {
log.Fatal(err) // do some reasonable error handling here
}
See the result on the Go Playground.