Go型交换机中的代码复制

Go型交换机中的代码复制,go,Go,刚开始编写Go代码,我遇到了一个有趣的问题 有没有一种方法可以轻松地迭代作为空接口引入的数组中的项,而无需代码重复?考虑以下事项: function(someArr interface{}){ switch someArr.(type){ case []int : arr := (someArr).([]int) for i := range (arr) { // CODE } case []string

刚开始编写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
        }
  } 
}
在本例中,代码中的代码完全相同。但是,我无法将其从开关中取出,因为类型断言arr将超出范围。类似地,我不能在切换之前定义arr,因为我不知道它将是什么类型。这很可能是不可能做到的。在这种情况下,当我用一个不规则的模式(一些int数组、一些数组或字符串)解析JSON时,对于这类事情,有什么更好的习惯用法呢?

您可以使用包在任意切片上迭代。但是显式实现特殊情况(如
[]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”
导入“反映”
func-foo(值接口{}){
rv:=反射值(值)
如果rv.Kind()!=reflect.Slice{
返回
}
n:=rv.Len()
对于i:=0;i

编辑:我不确定为什么有人否决了这个问题和我的答案,但在某些情况下,您需要处理类似的代码。即使是标准库也包含了大量的信息,比如“fmt”、“gob”、“json”、“xml”和“template”。提问者可能会面临类似的问题。

您的示例不是惯用的Go代码,尽管惯用的Go代码在词汇上似乎也违反了DRY原则

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

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

那么,这是否意味着不可能避免在“代码”中重复代码?但是,除了惯用的注释之外,这似乎没有解决代码重用的问题,除非我遗漏了什么?但是谢谢你给我关于习语的提示@ErikHinton:Go是一种强类型语言。“相同”的代码实际上是特定于类型的,因此不适合任何类型的合并。例如,在Haskell(另一种强静态类型语言)中,您可以编写类型类多态代码,这样,只要可能的类型具有可接受的实现,相同的函数就可以对它们进行操作。我想我可以在数组类型上使用一个通用接口来做类似的事情,以生成特殊的相等和长度方法,但这似乎很麻烦。@ErikHinton:我认为在Go中最接近这一点的是类型转换
someArr
[]接口{}
,然后让
code
对其进行操作。@Sammusmann:Go中没有类型转换。此外,当
T
尚未转换为
interface{}
时,不能将
[]T
转换为
[]interface{}
。您可以对其稍加修改。开关arr:=someArr.(type){;case[]int:;for i:=range arr{…}这是一个很好的清理。我将继续这样做。