我刚遇到的问题是在以下情况下该怎么办:
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没有泛型,也不允许使用集合协方差:
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
想法?
答案 0 :(得分:7)
如果没有
,现在还没有办法做到这一点[]int
和[]float
都改为[]interface{}
。interface{}
而不是[]interface{}
,然后使用反射,类似于fmt包的功能。两种解决方案都不是很好。
答案 1 :(得分:7)
我很惊讶没有人提到使用界面解决问题,这是一种非常惯用的方法,如果有点笨重:
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))
}
通过为每种类型定义列表的大小和索引,您可以“通用”地访问它们。当然,泛型仍然很好,所以你不必这样做。
答案 2 :(得分:5)
使用反射的一个例子:
package main
import (
"fmt"
"reflect"
"strings"
"container/vector"
)
func printItems(header string, items interface{}, fmtString string) {
value, ok := reflect.NewValue(items).(reflect.ArrayOrSliceValue)
if !ok {
panic("Not an array or slice")
}
stringBuilder := new(vector.StringVector)
stringBuilder.Push(header)
n := value.Len()
for i := 0; i < n; i++ {
stringBuilder.Push(fmt.Sprintf(fmtString, value.Elem(i).Interface()))
}
fmt.Println(strings.Join(*stringBuilder, ""))
}
func main() {
var iarr = []int{1, 2, 3}
var farr = []float{1.0, 2.0, 3.0}
printItems("Integer array:", iarr, " %d,")
printItems("Float array:", farr, " %.1f,")
}
答案 3 :(得分:2)
package main
import "fmt"
func printItems(header string, items interface{}, fmtString string) {
if intItems, ok := items.([]int); ok {
fmt.Println(header, intItems)
} else if floatItems, ok := items.([]float64); ok {
fmt.Println(header, floatItems)
}
}
func main() {
var iarr = []int{1, 2, 3}
var farr = []float64{1.0, 2.0, 3.0}
printItems("Integer array:", iarr, "")
printItems("Float array:", farr, "")
}
恕我直言,更优雅然后使用反射解决方案。
答案 4 :(得分:0)
package main
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包documentation和source code中查看类似的函数,例如fmt.Printf()。