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]
}
}
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, eg:
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 .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.