Go: How to get length of slice in function?

huangapple go评论82阅读模式
英文:

Go: How to get length of slice in function?

问题

我有一个函数,我想要在其中输入不同类型的切片,然后循环遍历它们并打印它们的内容。以下代码是有效的:

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

你有什么办法可以获取切片的长度,以便我可以循环遍历它吗?

英文:

I've got a function to which I want to feed different kinds of slices after which I want to loop over them and print their contents. The following code works:

func plot(data interface{}){
	fmt.Println(data)
	//fmt.Println(len(data))
}

func main() {
	l := []int{1, 4, 3}
	plot(l)
}

But when I uncomment the line in which I print the length of the slice, I get an error saying invalid argument data (type interface {}) for len.

Any idea how I would be able to get the length of the slice so that I can loop over it?

答案1

得分: 3

在可能的情况下,应尽量避免使用interface{}。你想要做的事情可以通过反射来实现,但反射是一种必要的恶。它非常适用于编组,但应该谨慎使用。如果你仍然想要使用reflect,可以像这样做:

func plot(data interface{}) {
    s := reflect.ValueOf(data)
    if s.Kind() != reflect.Slice {
        panic("plot()给定了一个非切片类型")
    }

    for i := 0; i < s.Len(); i++ {
        v := s.Index(i)
        // ...
    }
}

即使这样做了,v仍然是一个reflect.Value。然后你需要以某种方式将其转换为有用的类型。幸运的是,Value有许多方法可以用来进行转换。在这种情况下,v.Int()会将值作为int64返回。

英文:

You should try to avoid using interface{} whenever possible. What you want to do can be done with reflection, but reflection is a necessary evil. It is really good for marshalling, but should be used sparingly. If you still want to use reflect, you can do something like this:

func plot(data interface{}) {
	s := reflect.ValueOf(data)
	if s.Kind() != reflect.Slice {
		panic(&quot;plot() given a non-slice type&quot;)
	}

	for i := 0; i &lt; s.Len(); i++ {
		v := s.Index(i)
        ...
	}
}

Even after doing this, v is a reflect.Value. You will then need to somehow convert that to something useful. Luckily, Value has many methods that can be used to convert it. In this case, v.Int() would return the value as an int64.

答案2

得分: 1

根据评论中的提示,你需要使用反射来实现这个功能,类似以下的代码:

var sliceLen int

switch reflect.TypeOf(data).Kind() {
    
    case reflect.Slice:
        sliceLen = s.Len();
    default:
        // 在这里报错,出现了意外情况
    }
}

尽管Go语言提供了反射来实现这些小技巧(以及其他许多用途),但为了保持编译器类型安全和性能,通常最好尽量避免使用反射,考虑使用针对不同数据类型的单独函数的优缺点。

英文:

As hinted in comments you would have to use reflection to do this, something like the following:

var sliceLen int

switch reflect.TypeOf(data).Kind() {
    
    case reflect.Slice:
        sliceLen = s.Len();
    default:
        //error here, unexpected
    }
}

Although go provides reflection to do these little tricks when you need to (as well as many other uses), it is often better to avoid wherever possible to maintain compiler type safety and performance, consider the pros/cons of having separate functions for different data types over this approach

huangapple
  • 本文由 发表于 2017年9月7日 01:38:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/46081296.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定