Go类型开关中的代码复制

Eri*_*ton 4 go

刚刚开始编写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
        }
  } 
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,CODE中的代码完全相同.但是,我无法将其从交换机中取出,因为类型断言arr将超出范围.同样,我无法在切换之前定义arr,因为我不知道它将是什么类型.这可能无法完成.在那种情况下,当我用一个不规则的模式(某些数组的int,某些数组或字符串)解析JSON时,对于这种事情有什么更好的习惯用法?

tux*_*21b 6

您可以使用反射包迭代任意切片.但是[]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})
}
Run Code Online (Sandbox Code Playgroud)

编辑:我不确定为什么有人拒绝投票问题和答案,但有些情况下你需要处理这样的代码.即使是标准库也包含大量内容,请查看"fmt","gob","json","xml"和"template"等.提问者可能会遇到类似的问题.


zzz*_*zzz 6

你的例子不是惯用的Go代码,即使惯用的词汇似乎也违反了DRY原则.

要理解的关键点是'x' 在每种类型的情况下都是一个单独的,不同类型的变量:

function(someArr interface{}){
        switch x := someArr.(type) {
        case []int:
                for i := range x {
                        // CODE
                }
        case []string:
                for i := range x {
                        // CODE
                }
        }
}
Run Code Online (Sandbox Code Playgroud)