获取使用反射在Golang中创建的结构体的指针。

huangapple go评论91阅读模式
英文:

Get a pointer to a struct created using reflect in golang

问题

我有以下代码,模拟了我正在处理的代码的结构。主要思想是ListOf函数接收一个某种结构的数组,并使用反射创建元素并填充数组。结构的类型是未知的,所以它必须能够处理"任何"类型,这就是为什么将list参数传递为interface{}的原因。这部分似乎是有效的:元素被创建并附加到数组中。

在附加到数组之前,元素必须传递给SetValue函数,该函数期望接收一个指向结构的指针,以便修改接收到的结构。

在下面的代码中,我模拟了这个函数,它的内部逻辑不重要,因为我无法控制这个函数。我不能改变它,并且据我测试,如果这个函数接收到一个结构的指针,它会按预期工作。

然而,我一直无法找到一种方法来将新创建的结构的指针传递给SetValue函数。当我运行下面的代码时,我得到以下错误:

panic: interface conversion: interface {} is main.MyStruct, not *main.MyStruct

我的问题是,我如何修改ListOf函数,以便能够将*main.MyStruct传递给SetValue函数。显然,我在这里漏掉了一些简单的东西。

这是代码。你可以在Go Playground上尝试它。提前感谢。

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 order to modify obj
	// I don't 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)
}
英文:

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 order to modify obj
	// I don't 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)
}

答案1

得分: 3

New 返回一个带有 *main.MyStruct 类型的值。将该值传递给 SetValue 函数:

v := reflect.New(e)
SetValue(v.Interface())

https://go.dev/play/p/vJwbfGj7YZF

英文:

New returns a value with a *main.MyStruct. Pass that value to SetValue:

v := reflect.New(e)
SetValue(v.Interface())

https://go.dev/play/p/vJwbfGj7YZF

huangapple
  • 本文由 发表于 2022年10月2日 00:04:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/73919825.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定