I have the following code that mocks the structure of a code I'm working on. The main idea is that the ListOf
function receives an array of some struct and populates it with elements created using reflection. The type of the structs is unknown so it must work with "any" type, this is why the list
parameter is passed as interface{}
. This part seems to be working: elements are created and appended to the array.
Before appending to the the array, the elements must be passed to the SetValue
function which expects a pointer to a struct in order to modify the struct it receives.
In the code below I'm mocking this function, its internal logic is not relevant because I don't control this function. I cannot change it and, as far as I have tested, if this function receives a pointer to a struct it works as expected.
However, I have been unable to find a way to pass a pointer to the new created struct to the SetValue
function. When I run the code below I get the following error:
panic: interface conversion: interface {} is main.MyStruct, not *main.MyStruct
The question I have is, how can I modify ListOf
to be able to pass a *main.MyStruct
to the SetValue
function. Apparently I'm missing something simple here.
This is the code. You can try it at the Go Playground. Thanks in advance.
package main
import (
"fmt"
"reflect"
)
type MyStruct struct {
Metadata struct {
Name string
}
}
// Expects a pointer to an struct and modifies it
func SetValue(obj interface{}) {
// This code mocks the logic that modifies the generic objects
// It only shows that I need a pointer in oder to modidy obj
// I dont control this logic.
s := obj.(*MyStruct)
s.Metadata.Name = "name"
}
func ListOf(list interface{}) {
// type of the elements of the list (main.MyStruct)
e := reflect.TypeOf(list).Elem().Elem()
// new value of type main.MyStruct
v := reflect.New(e)
// Call SetName, here is where I need *main.MyStruct
SetValue(v.Elem().Interface())
// value of list used below
l := reflect.ValueOf(list).Elem()
// append new value to list
l.Set(reflect.Append(l, v.Elem()))
}
func main() {
list := []MyStruct{}
ListOf(&list)
fmt.Printf("%v", list)
}
CodePudding user response:
New
returns a value with a *main.MyStruct
. Pass that value to SetValue:
v := reflect.New(e)
SetValue(v.Interface())