Home > database >  Assign values from slice of unknown length to struct in Go?
Assign values from slice of unknown length to struct in Go?

Time:07-04

I find the case below from some useful packages in github and it looks so ugly and stupid. I think the better design of code can avoid this, but if we meet this, can it be written more concisely?

Is there a better way to do that instead of continuous checking by slice length?

package main

type NumberSet struct {
    SetName string
    Number1 int
    Number2 int
    Number3 int
}

func main() {
    set := &NumberSet{SetName: "test"}
    var numbers []int
    // assume that we don't know the actual length of slice
    numbers = append(numbers, 1)
    numbers = append(numbers, 2)

    length := len(numbers)
    if length > 0 {
        set.Number1 = numbers[0]
    }
    if length > 1 {
        set.Number2 = numbers[1]
    }
    if length > 2 {
        set.Number3 = numbers[2]
    }
}

CodePudding user response:

You could use a for range to range over the numbers, so you can omit the length check, and use a switch for field assignment, e.g.:

for i, v := range numbers {
    switch i {
    case 0:
        set.Number1 = v
    case 1:
        set.Number2 = v
    case 2:
        set.Number3 = v
    }
}

Try it on the Go Playground.

You may also list the addresses of the fields in another slice, and use a single loop to do the assignments:

ps := []*int{&set.Number1, &set.Number2, &set.Number3}
for i, v := range numbers {
    *ps[i] = v
}

Try it on the Go Playground.

If performance is not critical and the fields you assign to are sequential, you may use reflection to do the assignments without having to enumerate the fields, for example:

rv := reflect.ValueOf(set).Elem()
for i, v := range numbers {
    rv.Field(1   i).Set(reflect.ValueOf(v)) // 1 is the offset of Number1
}

Try it on the Go Playground.

  • Related