简体   繁体   English

如何使用反射将结构的每个字段设置为 go 中的非零值

[英]How to use reflect to set every field of struct to non-nil value in go

Suppose I have some type, and I want to instantiate a variable of this type, with every value non-nil.假设我有一些类型,我想实例化一个这种类型的变量,每个值都不是零。

type Event struct {
    HappenedAtMs   int64 
    ReceivedAtMs   int64
    FieldA         *FieldAType
    FieldB         []*FieldBType

Here is what I am currently trying:这是我目前正在尝试的:

    eventFields := reflect.TypeOf(Event{})

    event := Event{}
    for i := 0; i < eventFields.NumField(); i++ {
        nonEmptyType := reflect.New(eventFields.Field(i).Type).Elem()
        reflect.ValueOf(&event).Elem().Field(i).Set(nonEmptyType)
    }

However, upon running this code, all the fields in the event variable are still set to nil.但是,运行此代码后,事件变量中的所有字段仍设置为 nil。 How can I achieve what I want?我怎样才能达到我想要的?

The reflect package needs a pointer to the struct for it to be able to set its fields. reflect package 需要一个指向该结构的指针才能设置其字段。 The fields also need to be exported which you can check against using the CanSet method.还需要导出字段,您可以使用CanSet方法对其进行检查。

To initialize a pointer type with reflect you can simply do reflect.New(T.Elem()) .要使用reflect初始化指针类型,您可以简单地执行reflect.New(T.Elem()) To initialize a map , a slice , a func , or a chan type to non-nil you can use the MakeMap , MakeSlice , MakeFunc , and MakeChan functions respectively.要将mapslicefuncchan类型初始化为非零类型,您可以分别使用MakeMapMakeSliceMakeFuncMakeChan函数。 To initialize an interface type to non-nil you can create an anonymous struct type, using reflect.StructOf , with a single embedded field of the target interface type, by embedding the interface type the struct type automatically satisfies the interface and an instance of it can be used to set the field to non-nil.要将接口类型初始化为非零,您可以使用reflect.StructOf创建一个匿名结构类型,其中包含目标接口类型的单个嵌入字段,通过嵌入接口类型,结构类型自动满足接口及其实例可用于将字段设置为非零。

event := Event{}

rv := reflect.ValueOf(&event).Elem()
for i := 0; i < rv.NumField(); i++ {
    if f := rv.Field(i); isNilable(f) && f.IsNil() && f.CanSet() {
        switch f.Kind() {
        case reflect.Ptr:
            f.Set(reflect.New(f.Type().Elem()))
        case reflect.Slice:
            f.Set(reflect.MakeSlice(f.Type(), 0, 0))
        case reflect.Interface:
            sf := reflect.StructField{
                Name:      f.Type().Name(),
                Type:      f.Type(),
                Anonymous: true,
            }
            rt := reflect.StructOf([]reflect.StructField{sf})
            f.Set(reflect.New(rt).Elem())
            // TODO handle the rest of nilable types
        }
    }
}

https://play.golang.com/p/nQqvUIROqF- https://play.golang.com/p/nQqvUIROqF-

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM