我有一个功能,我想要提供不同类型的切片,之后我想循环它们并打印它们的内容。以下代码有效:
func plot(data interface{}){
fmt.Println(data)
//fmt.Println(len(data))
}
func main() {
l := []int{1, 4, 3}
plot(l)
}
但是当我取消注释我打印切片长度的行时,我收到错误invalid argument data (type interface {}) for len
。
知道我怎么能够获得切片的长度以便我可以循环它?
答案 0 :(得分:3)
您应该尽可能避免使用接口{}。你想做的事情可以通过反思来完成,但反思是必要的邪恶。它对编组非常有用,但应该谨慎使用。如果你仍想使用反射,你可以这样做:
func plot(data interface{}) {
s := reflect.ValueOf(data)
if s.Kind() != reflect.Slice {
panic("plot() given a non-slice type")
}
for i := 0; i < s.Len(); i++ {
v := s.Index(i)
...
}
}
即使这样做,v也是reflect.Value。然后,您需要以某种方式将其转换为有用的东西。幸运的是,Value有许多方法可用于转换它。在这种情况下,v.Int()
会将值作为int64返回。
答案 1 :(得分:1)
正如评论中暗示的那样,您必须使用反射来执行此操作,如下所示:
var sliceLen int
switch reflect.TypeOf(data).Kind() {
case reflect.Slice:
sliceLen = s.Len();
default:
//error here, unexpected
}
}
虽然go提供了在需要时(以及许多其他用途)执行这些小技巧的反思,但通常最好避免在任何可能的情况下维护编译器类型的安全性和性能,考虑具有单独功能的优点/缺点对于这种方法的不同数据类型