Just getting started writing Go code and I ran into an interesting problem.
Is there a way to easily iterate over the items in an array that is brought in as an empty interface without code duplication? Consider the following:
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
}
}
}
In this example the code in CODE is exactly the same. However, I cannot take it out of the switch because the type assertion arr would fall out of scope. Similarly, I can't define arr before the switch because I don't know what type it will be. It's possible that this just cannot be done. In that case, what's a better idiom for this kind of thing when I'm, say, parsing JSON with an irregular schema (some arrays of ints, some arrays or strings)?
Your example is not idiomatic Go code, even though the idiomatic one lexically seems violating the DRY principle as well.
The key point to understand is that 'x' is a separate, differently typed variable in each type case:
function(someArr interface{}){
switch x := someArr.(type) {
case []int:
for i := range x {
// CODE
}
case []string:
for i := range x {
// CODE
}
}
}
You can use the reflect package to iterate over arbitrary slices. But implementing the special cases (like []int
) explicitly is generally faster and is often done in addition to avoid reflection in common cases.
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})
}
Edit: I'm not sure why somebody has down voted the question and my answer, but there are cases where you need to deal with code like that. Even the standard library contains plenty of it, take a look at "fmt", "gob", "json", "xml" and "template" for example. The questioner might face a similar problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With