以下是我遇到的问题的一个例子:
package main
import "fmt"
func foo(a int, b ...int) {
fmt.Println(a,b)
}
func main() {
a := 0
aa := 1
b := []int{2,3,4}
foo(a, aa, b...)
}
当我运行此操作时,我收到错误too many arguments in call to foo
。我想我可以理解为什么会发生这种情况,但我不清楚的是我如何绕过它而不必在b
开头添加aa
一个额外的插槽我宁愿不这样做,因为这段代码会经常运行,并且b
有点长。)
所以我的问题是:我这样做错了吗?如果没有,那么最有效的方法是做我想做的事情?
(另外,我无法更改foo
)的签名。
答案 0 :(得分:13)
在Go运行时,可变参数函数为implemented,就好像它在末尾有一个额外的slice参数而不是一个可变参数。
例如:
func Foo( a int, b ...int )
func FooImpl( a int, b []int )
c := 10
d := 20
//This call
Foo(5, c, d)
// is implemented like this
b := []int{c, d}
FooImpl(5, b)
理论上Go可以处理直接指定一些可变参数的情况,其余参数从数组/切片中扩展出来。但是,它效率不高。
//This call
Foo(5, c, b...)
// would be implemented like this.
v := append([]int{c},b...)
FooImpl(5, v)
你可以看到Go会创建b
的副本。 The ethos of Go is to be as small as possible and yet still useful。所以像这样的小功能会被丢弃。你或许可以争论这种语法糖,因为它可以比append
的直接方法更有效地实施。
请注意expanding a slice with ...
does not create a copy of the underlying array用作参数。该参数只是变量的别名。换句话说,它真的很有效率。
答案 1 :(得分:8)
您可以这样做:
package main
import "fmt"
func foo(a int, b ...int) {
fmt.Println(a,b)
}
func main() {
a := 0
aa := 1
b := []int{2,3,4}
foo(a, append([]int{aa}, b...)...)
}
预计b ...int
时,您需要传递[]int...
或int
作为参数。不要混用int
和[]int...