【问题标题】:go (reflect): How to Instantiate an arbitrary type and set a known embedded fieldgo (reflect): 如何实例化任意类型并设置已知的嵌入字段
【发布时间】:2015-11-15 16:09:51
【问题描述】:

考虑以下类型声明:

type (
    Embedded struct{}
    Actual1 struct{ *Embedded }
    Actual2 struct{ *Embedded }
    Actual3 struct{ *Embedded }
)

现在考虑以下函数,其中i 可能是Actual1Actual2Actual3 类型(或以类似方式嵌入Embedded 的任何其他类型)。我无法进行类型断言或类型切换,因为我不知道有多少类型包含Embedded,我所知道的i 是它确实嵌入了Embedded 类型。该函数将实例化一个与i 相同类型的新实例,并在该新实例化的副本实例上设置embed

func New(i interface{}, field *Embedded) interface{} {
    // Step 1. instantiate new instance of `i`, of same underlying type as `i`
    // Step 2. set `i.Embedded` to `field`
    // Step 3. return the new instance.
}

以下是用法:

func main() {
    actual := &Actual1{}
    embed := &Embedded{}
    copied := New(actual, embed)
    if copied.(Actual1).Embedded != embed {
        log.Fatal("It didn't work!")
    }
}

New(...) 函数的正确实现不能使用类型断言或类型切换,也不会导致对上面显示的log.Fatal 的调用。

我想我要问的是这两个问题的结合:

【问题讨论】:

    标签: reflection go


    【解决方案1】:

    使用反射,你可以这样做:

    • 从指向它的指针的类型中获取结构的类型
    • 实例化并取消引用它
    • 使用指针的值设置字段的值(按名称查找)

    代码:

    v := reflect.New(reflect.TypeOf(i).Elem()).Elem()
    f := reflect.ValueOf(field)
    v.FieldByName("Embedded").Set(f)
    return v.Interface()
    

    游乐场:http://play.golang.org/p/fX413svXDv

    【讨论】:

    • 完美!我在 TypeOf(i) 之后错过了 .Elem() 调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-10
    • 2014-07-14
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多