在 Go 中将未知长度的切片中的值分配给结构?

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

提问人:sasakiyori 提问时间:7/4/2022 最后编辑:blackgreensasakiyori 更新时间:7/4/2022 访问量:111

问:

我从 github 中的一些有用的包中找到了下面的案例,它看起来非常丑陋和愚蠢。我认为更好的代码设计可以避免这种情况,但是如果我们满足了这一点,它能写得更简洁吗?

有没有更好的方法可以做到这一点,而不是按切片长度连续检查?

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]
    }
}
go struct 切片

评论


答:

2赞 icza 7/4/2022 #1

您可以使用 a 来对数字进行范围调整,这样您就可以省略长度检查,并使用 a 进行字段分配,例如:for rangeswitch

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

Go Playground 上尝试一下。

您还可以在另一个切片中列出字段的地址,并使用单个循环来执行分配:

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

Go Playground 上尝试一下。

如果性能不重要,并且您分配到的字段是连续的,则可以使用反射来执行分配,而无需枚举字段,例如:

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

Go Playground 上尝试一下。