如何使用反射初始化结构中的零个切片

时间:2020-11-06 11:04:51

标签: go struct reflection slice

对于任何给定的struct,我想遍历其字段并将所有nil slice设置为空切片。但是,切片无法寻址,因此无法设置。如何设置任何零切片的值?

示例: https://goplay.space/#iV6OHkYVTru

package main

import (
    "fmt"
    "reflect"
)

type Foo struct {
    IntSlice []int
    StrSlice []string
}

func main() {
    foo := Foo{}
    fmt.Println(foo.IntSlice == nil)
    initNilSlices(foo)
    fmt.Println(foo.IntSlice == nil)
}

func initNilSlices(x interface{}) {
    v := reflect.ValueOf(x)
    for i := 0; i < v.NumField(); i++ {
        f := v.Field(i)
        if f.Kind() == reflect.Slice {
            t := f.Type()
            f.Set(reflect.MakeSlice(t, 0, 0))
        }
    }
}

1 个答案:

答案 0 :(得分:3)

如果您通过foo,则无法更新/修改initNilSlices()中的foo,因为这将是副本,并且您只能修改副本(而不是原始值)

这是错误消息“提示”:

panic: reflect: reflect.Value.Set using unaddressable value

您是从非指针值获得的reflect.Value,甚至reflect.ValueOf()都得到了一个副本,因此它不允许您修改它,因为它不是您想要的想要。

您必须传递foo的地址:

initNilSlices(&foo)

initNilSlices()中使用Value.Elem()

v := reflect.ValueOf(x).Elem()

通过它可以工作并输出(在Go Playground上尝试):

true
false