假设我有某种类型,并且我想实例化此类型的变量,并且每个值都不为nil。

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


这是我目前正在尝试的方法:
    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)
    }

但是,运行此代码后,事件变量中的所有字段仍设置为nil。我怎样才能实现自己想要的?

最佳答案

reflect包需要一个指向该结构的指针,以便它能够设置其字段。还需要导出字段,您可以使用CanSet方法进行检查。

要使用reflect初始化指针类型,您只需执行reflect.New(T.Elem())即可。要将mapslicefuncchan类型初始化为nonnil,可以分别使用MakeMapMakeSliceMakeFuncMakeChan函数。要将接口(interface)类型初始化为非nil,可以使用reflect.StructOf创建一个匿名结构类型,并在目标接口(interface)类型的单个嵌入字段中嵌入该接口(interface)类型,从而使结构类型自动满足该接口(interface)的要求,并且该接口(interface)的实例可以是用于将字段设置为非零。

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-

10-08 04:44