gpt4 book ai didi

go - 如何在没有嵌套循环的情况下将嵌套结构塑造成另一个结构?

转载 作者:数据小太阳 更新时间:2023-10-29 03:41:13 25 4
gpt4 key购买 nike

如何将 A 和 B 的选定值注入(inject)下面的子 C?

decoder.go ( Playground link )

package main

import (
"fmt"
)

type Input struct {
A []A
}

type A struct {
AID int
B []B
}

type B struct {
BID int
C []C
}

type C struct {
// I want to inject only AID and BID here
// But, without injecting A and B directly
// (without recursively)
CID int
}

func main() {
res := Input{
A: []A {
A {
AID: 1,
B: []B {
B{ BID: 11, C: []C{{ 111 }, { 111 }}},
B{ BID: 12, C: []C{{ 121 }, { 122 }}},
},
},
A {
AID: 2,
B: []B {
B{ BID: 21, C: []C{{ 211 }, { 211 }}},
B{ BID: 22, C: []C{{ 221 }, { 222 }}},
},
},
},
}

// I want to inject AID and BID into C
// WITHOUT nested loops like this:
for _, a := range res.A {
for _, b := range a.B {
for _, c := range b.C {
fmt.Println(a.AID, b.BID, c.CID)
}
}
}
}

最佳答案

如果您不想使用嵌套循环,一种解决方案是使用递归调用和反射将特性/特性注入(inject)到结构中。在下面的实现中,要注入(inject)的属性/特性被包装在结构实现 Injectable 接口(interface)中。可以在 Go Playground 找到工作示例.

  1. 定义接口(interface)。

    type Injectable interface {
    InjectTo(v interface{})
    }
  2. 定义包含要注入(inject)的特性/属性的数据结构,例如

    type Property struct {
    AID int
    BID int
    }

    type C struct {
    // The properties will be injected here
    Property
    CID int
    }
  3. 使用反射和递归调用实现InjectTo

    //Method must be pointer receiver since p will be used 
    //as temporary placeholder for parent properties/attributes.
    func (p *Property) injectRecursive(v reflect.Value, it reflect.Type, pv reflect.Value) {
    switch v.Kind() {
    case reflect.Struct:
    vt := v.Type()
    //Embedded struct is a 'value' type implement Injectable
    if vt.Implements(it) {
    //Inject value to embedded struct
    ot := pv.Type()
    for k := 0; k < pv.NumField(); k++ {
    name := ot.Field(k).Name
    f := v.FieldByName(name)
    if f.CanSet() {
    f.Set(pv.Field(k))
    }
    }
    } else {
    for k := 0; k < v.NumField(); k++ {
    fv := v.Field(k)

    //Match by field name.
    //For more robust and generic solution
    //consider using other approach, e.g. tag
    f := pv.FieldByName(vt.Field(k).Name)
    if f.CanSet() {
    f.Set(fv)
    } else {
    p.injectRecursive(fv, it, pv)
    }
    }
    }
    case reflect.Slice, reflect.Array:
    for k := 0; k < v.Len(); k++ {
    p.injectRecursive(v.Index(k), it, pv)
    }
    case reflect.Ptr:
    if v.IsValid() {
    p.injectRecursive(v.Elem(), it, pv)
    }
    }
    }

    //InjectTo must be Value (not pointer) receiver
    func (p Property) InjectTo(s interface{}) {
    sv := reflect.Indirect(reflect.ValueOf(s))
    pv := reflect.Indirect(reflect.ValueOf(&p))
    it := reflect.TypeOf((*Injectable)(nil)).Elem()
    p.injectRecursive(sv, it, pv)
    }
  4. 您可以通过以下方式注入(inject)属性:

    res := Input{...}
    prop := Property{}
    prop.InjectTo(&res)

关于go - 如何在没有嵌套循环的情况下将嵌套结构塑造成另一个结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44442336/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com