刚开始编写Go代码,我遇到了一个有趣的问题。
有没有办法轻松迭代数组中的项目,这些项目作为空接口引入而没有代码重复?请考虑以下事项:
function(someArr interface{}){
switch someArr.(type){
case []int :
arr := (someArr).([]int)
for i := range (arr) {
// CODE
}
case []string :
arr := (someArr).([]string)
for i := range (arr) {
// CODE
}
}
}
在此示例中,CODE中的代码完全相同。但是,我无法将其从交换机中取出,因为类型断言arr将超出范围。同样,我无法在切换之前定义arr,因为我不知道它将是什么类型。这可能无法完成。在那种情况下,当我使用不规则的模式(某些数组的int,某些数组或字符串)解析JSON时,这种事情的更好的习惯是什么?
答案 0 :(得分:6)
您可以使用reflect包来迭代任意切片。但是,明确地实现特殊情况(如[]int
)通常更快,并且除了避免在常见情况下反映外,通常也会这样做。
package main
import "fmt"
import "reflect"
func foo(values interface{}) {
rv := reflect.ValueOf(values)
if rv.Kind() != reflect.Slice {
return
}
n := rv.Len()
for i := 0; i < n; i++ {
value := rv.Index(i).Interface()
fmt.Println(value)
}
}
func main() {
foo([]int{1, 3, 3, 7})
}
编辑:我不确定为什么有人拒绝投票给我问题和答案,但有些情况下你需要处理这样的代码。即使是标准库也包含大量内容,请查看“fmt”,“gob”,“json”,“xml”和“template”等。提问者可能会遇到类似的问题。
答案 1 :(得分:6)
你的例子不是惯用的Go代码,即使惯用的 lexically 似乎也违反了DRY原则。
要理解的关键点是'x'是单独的,在每种类型的情况下输入不同的变量:
function(someArr interface{}){
switch x := someArr.(type) {
case []int:
for i := range x {
// CODE
}
case []string:
for i := range x {
// CODE
}
}
}