Go:Variadic函数和太多参数?

时间:2013-09-22 17:42:29

标签: go variadic-functions

以下是我遇到的问题的一个例子:

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)的签名。

2 个答案:

答案 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...