samedi 1 octobre 2022

Get a pointer to a struct created using reflect in golang

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)
}




Aucun commentaire:

Enregistrer un commentaire