你如何遍历Golang结构中的字段以获取和设置值的可扩展方式? [英] How do you loop through the fields in a Golang struct to get and set values in an extensible way?

查看:118
本文介绍了你如何遍历Golang结构中的字段以获取和设置值的可扩展方式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 类型Person结构{
名字字符串
姓氏字符串
年uint8
}

然后我有这个结构的两个实例PersonA和PersonB。

  PersonA:= {,Obama,6} 
PersonB:= {President ,Carter,8}

我想写一个函数将PersonA中的值复制到PersonB给每个领域一些条件(即非空)。我知道如何通过硬编码字段名来完成此任务,但是我想要一个即使更改Person结构也能正常工作的函数。

我知道Go反射是有帮助的,但问题在于如何设置值需要知道类型,如果您想使用SetInt之类的东西。但是,有没有一种简单的方法来做到这一点?

** Javascript类比**
在Javascript中,您可以对someObject中的属性进行循环。

 (对于persona中的propt){
if personA [propt]!={
//做某事
personB [propt] = personA [propt]
}
}

我排除的选项:


  1. 跟踪地图中每个结构中的字段,然后在反映pkg 中使用FieldByName和Set *函数集合的组合。


  2. 手动创建一个通过Person字段的循环(下图)。因为我想为许多其他结构(学校,动物等等)做这种类型的更新。

      if PersonA.Firstname!={
    PersonB.Firstname = PersonA.Firstname
    }

    ...

      if PersonA.Years!={
    PersonB.Years = PersonA.Years
    }




  3. 我在那里一半,但仍然不能扩展到我想要利用这个更新功能的所有结构。



    **其他有用的链接**
    GoLang:按名称访问结构属性

    解决方案

    以下是解决方案 f2.Set(reflect.Value(f))是关键这里

      package main 

    import(
    fmt
    反映


    func main(){
    type T struct {
    A int
    B string
    }
    t:= T {23,skidoo}
    t2:= T {}
    s:= reflect.ValueOf(& t).Elem()
    s2:= reflect。 ValueOf(& t2).Elem()
    typeOfT:= s.Type()
    fmt.Println(t =,t)
    fmt.Println(t2 =, t2)

    for i:= 0;我< s.NumField(); i ++ {
    f:= s.Field(i)
    f2:= s2.Field(i)
    fmt.Printf(%d:%s%s =%v \\\
    ,i,
    typeOfT.Field(i).Name,f.Type(),f.Interface())
    fmt.Printf(%d:%s%s =%v \\\
    ,i,
    typeOfT.Field(i).Name,f2.Type(),f2.Interface())
    f2.Set(reflect.Value(f))
    fmt。 printf(%d:%s%s =%v \ n,i,
    typeOfT.Field(i).Name,f2.Type(),f2.Interface())


    fmt.Println(t =,t)
    fmt.Println(t2 =,t2)
    }

    输出:

    t = {23 skidoo}
    t2 = {0}
    0:A int = 23
    0:A int = 0
    0:A int = 23
    1:B string = skidoo
    1:B string =
    1:B string = skidoo
    t = {23 skidoo}
    t2 = {23 skidoo}

    http://play.golang.org/p/UKFMBxfbZD


    I have a struct Person.

    type Person struct {
        Firstname string       
        Lastname  string       
        Years     uint8       
    }
    

    Then I have two instances of this struct, PersonA and PersonB.

    PersonA := {"", "Obama", 6}
    PersonB := {"President", "Carter", 8}
    

    I want to write a function that copies the values from PersonA to PersonB given some condition for each field (i.e. non-empty). I know how to do this by hard-coding the field names, but I want a function that works even if I change the Person struct.

    I know Go reflections is helpful, but the issue is getting and setting the values requires knowing the types, if you want to use something like SetInt. But is there is a "simple" way to do this?

    ** Javascript analogy ** In Javascript, you could just do a (for property in someObject) to loop through.

    (for propt in personA) {
      if personA[propt] != "" {
        // do something
        personB[propt] = personA[propt]
      }
    }
    

    Options I've ruled out:

    1. Keeping track of the fields in each struct in a map, then using a combination of FieldByName and the collection of Set* functions in the reflect pkg.

    2. Creating a loop through the fields of Person manually (below). Because I want to do this type of "update" for many other structs (School, Animals, etc...)

      if PersonA.Firstname != "" {
        PersonB.Firstname = PersonA.Firstname 
      }
      

      ...

      if PersonA.Years != "" {
        PersonB.Years = PersonA.Years 
      }
      

    The question below gets me half-way there, but still isn't extensible to all structs for which I want to utilize this "update" function.

    in golang, using reflect, how do you set the value of a struct field?

    ** Other Helpful Links ** GoLang: Access struct property by name

    解决方案

    Here is the solution f2.Set(reflect.Value(f)) is the key here

    package main
    
       import (
        "fmt"
        "reflect"
       )
    
       func main() {
        type T struct {
            A int
            B string
        }
        t := T{23, "skidoo"}
        t2:= T{}
        s := reflect.ValueOf(&t).Elem()
        s2 := reflect.ValueOf(&t2).Elem()
        typeOfT := s.Type()
        fmt.Println("t=",t)
        fmt.Println("t2=",t2)
    
        for i := 0; i < s.NumField(); i++ {
            f := s.Field(i)
            f2:= s2.Field(i)
            fmt.Printf("%d: %s %s = %v\n", i,
                typeOfT.Field(i).Name, f.Type(), f.Interface())
            fmt.Printf("%d: %s %s = %v\n", i,
                typeOfT.Field(i).Name, f2.Type(), f2.Interface())
            f2.Set(reflect.Value(f))
            fmt.Printf("%d: %s %s = %v\n", i,
                typeOfT.Field(i).Name, f2.Type(), f2.Interface())
    
        }
        fmt.Println("t=",t)
        fmt.Println("t2=",t2)
    }
    
    Output:
    
    t= {23 skidoo}
    t2= {0 }
    0: A int = 23
    0: A int = 0
    0: A int = 23
    1: B string = skidoo
    1: B string = 
    1: B string = skidoo
    t= {23 skidoo}
    t2= {23 skidoo}
    

    http://play.golang.org/p/UKFMBxfbZD

    这篇关于你如何遍历Golang结构中的字段以获取和设置值的可扩展方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆