The problem I've just faced is what to do in the following case:
func printItems(header string, items []interface{}, fmtString string) {
// ...
}
func main() {
var iarr = []int{1, 2, 3}
var farr = []float{1.0, 2.0, 3.0}
printItems("Integer array:", iarr, "")
printItems("Float array:", farr, "")
}
Go has no generics and doesn't allow to use collection covariance:
prog.go:26: cannot use iarr (type []int) as type []interface { } in function argument
prog.go:27: cannot use farr (type []float) as type []interface { } in function argument
Ideas?
I'm surprised nobody mentioned using an interface to solve the problem, which is a very idiomatic approach, if a little clunky:
package main
import "fmt"
type List interface {
At(i int) interface{}
Len() int
}
func printItems(header string, items List) {
for i := 0; i < items.Len(); i++ {
fmt.Print(items.At(i), " ")
}
fmt.Println()
}
type IntList []int
type FloatList []float64
func (il IntList) At(i int) interface{} { return il[i] }
func (fl FloatList) At(i int) interface{} { return fl[i] }
func (il IntList) Len() int { return len(il) }
func (fl FloatList) Len() int { return len(fl) }
func main() {
var iarr = []int{1, 2, 3}
var farr = []float64{1.0, 2.0, 3.0}
printItems("Integer array:", IntList(iarr))
printItems("Float array:", FloatList(farr))
}
By defining the size and indexing of the list for each type, you can access them "generically". Of course, generics would still be nice so you don't have to do this.
There's not really a way to do this right now without either
[]int
and []float
both into []interface{}
.interface{}
instead of []interface{}
and then use reflection, similar to what the fmt package does.Neither solution is pretty.
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