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.