【问题标题】:Update the fields of one struct to another struct将一个结构的字段更新为另一个结构
【发布时间】:2020-06-05 17:09:42
【问题描述】:

我有一个结构:

type Person struct {
    FirstName string
    LastName int
    Age int 
    HairColor string
    EyeColor string
    Height string
}

我有一个函数,它接受 2 个参数,并将第一个人的字段更新为第二个人的字段:

func updateFields(personA *Person, personB Person) {
    personA.FirstName = personB.FirstName
    personA.LastName = personB.LastName
    // Don't want to change Age.
    personA.HairColor = personB.HairColor
    personA.EyeColor = personB.EyeColor 
    personA.Height = personB.Height

}

除了对要更改的值进行硬编码之外,我如何循环遍历字段并将第一个 Person 更新为与第二个 Person 具有相同的值,但“Age”字段除外?

【问题讨论】:

  • 你可以做*personA = personB
  • 刚刚编辑了问题。我需要除其中一个以外的所有字段都相同
  • personB.Age = personA.Age 然后查看第一条评论 ;)。

标签: go struct


【解决方案1】:

您可以将整个personB 复制到personA 并在之前备份Age 字段:

func updateFields(personA *Person, personB Person) {
    tempAge := personA.Age
    *personA = personB
    personA.Age = tempAge
}

【讨论】:

    【解决方案2】:

    为了简单地复制每个字段,您可以简单地执行*personA = personB 之类的操作。如果您只需要“不复制”一个特定字段(每次都是相同的字段),您可能只需将该字段的值保存在一个单独的变量中,使用*personA = personB 复制所有内容,然后将值复制回来。但这仅对非常特定的情况有用。例如,它不允许有一组不复制的动态字段。

    如果你想更灵活地做到这一点,你可以使用反射来做到这一点,下面的示例代码。

    请注意,可能存在一些限制。值得注意的是,您只能设置导出的字段。此外,如果您不测试这些限制并且不小心尝试设置一个不可设置的字段,或者使用不可分配给该字段的类型值等,reflect 包将很高兴panic。因此,在您实际 .Set(...) 字段之前添加大量检查是明智的。

    import (
        "fmt"
        "reflect"
    )
    
    type Person struct {
        FirstName string
        LastName int
        Age int
        HairColor string
        EyeColor string
        Height string
    }
    
    func updateFields(personA *Person, personB Person) {
        // .Elem() called to dereference the pointer
        aVal := reflect.ValueOf(personA).Elem()
        aTyp := aVal.Type()
    
        // no .Elem() called here because it's not a pointer
        bVal := reflect.ValueOf(personB)
    
        for i := 0; i < aVal.NumField(); i++ {
            // skip the "Age" field:
            if aTyp.Field(i).Name == "Age" {
              continue
            }
            // you might want to add some checks here,
            // eg stuff like .CanSet(), to avoid panics
            aVal.Field(i).Set(bVal.Field(i))
        }
    }
    
    func main() {
        b := Person{
            FirstName: "Bruno",
            LastName:  1,
            Age:       2,
            HairColor: "hello",
            EyeColor:  "world",
            Height:    "tall",
        }
        a := Person{}
        fmt.Println(a)
        updateFields(&a, b)
        fmt.Println(a)
    }
    

    【讨论】:

    • 糟糕!忘记添加问题的另一部分。在上面编辑它。如果我想更新除 Age 字段之外的所有字段怎么办?
    猜你喜欢
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多