Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you loop through the fields in a Golang struct to get and set values in an extensible way?

Tags:

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

like image 973
platwp Avatar asked Apr 28 '14 20:04

platwp


People also ask

How do you loop through a struct in Go?

To loop through struct types in Go , makes use of the reflect package. The Reflect package implements run-time reflection, hence allowing a program to modify objects with arbitrary types. In the above example, we define User struct type with several attributes.

How to loop through a list in Golang?

In Golang, you can loop through an array using a for loop by initialising a variable i at 0 and incrementing the variable until it reaches the length of the array. In the code above, we defined an array of integers named numbers and looped through them by initialising a variable i .

How does struct work in Golang?

A structure or struct in Golang is a user-defined type that allows to group/combine items of possibly different types into a single type. Any real-world entity which has some set of properties/fields can be represented as a struct. This concept is generally compared with the classes in object-oriented programming.


1 Answers

Use reflect.ValueOf() to convert to concrete type. After that you could use reflect.Value.SetString to set the value you want.

structValue := FooBar{Foo: "foo", Bar: 10} fields := reflect.TypeOf(structValue) values := reflect.ValueOf(structValue)  num := fields.NumField()  for i := 0; i < num; i++ {     field := fields.Field(i)     value := values.Field(i)     fmt.Print("Type:", field.Type, ",", field.Name, "=", value, "\n")      switch value.Kind() {     case reflect.String:         v := value.String()         fmt.Print(v, "\n")     case reflect.Int:         v := strconv.FormatInt(value.Int(), 10)         fmt.Print(v, "\n")     case reflect.Int32:         v := strconv.FormatInt(value.Int(), 10)         fmt.Print(v, "\n")     case reflect.Int64:         v := strconv.FormatInt(value.Int(), 10)         fmt.Print(v, "\n")     default:         assert.Fail(t, "Not support type of struct")     } } 
like image 172
jtianling Avatar answered Oct 31 '22 05:10

jtianling