使用反射从未知的结构类型创建新的结构

问题描述 投票:0回答:2

我有一个函数期望接收指向未知定义的结构的指针数组。我希望能够创建未知结构的新实例,为其赋值,然后将其附加到给定的数组。

// 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.
}
go
2个回答
1
投票

试试这个代码:

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


0
投票

虽然 Jeremy 的答案是正确的,但结果

foos[0]
Foo{Val: 1, Nested: nil }
。通过 Reflect 设置层次结构值可能很棘手,所以我可以建议使用 JSON 吗?

首先生成一个新的

Foo
值并将其附加到切片中:

    t := reflect.ValueOf(target).Elem()
    foo := reflect.New(t.Type().Elem().Elem())
    t.Set(reflect.Append(t, foo))

然后使用 JSON 填写值

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
    }

在 Go Playground 查看结果。

© www.soinside.com 2019 - 2024. All rights reserved.