15

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

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)。

4

2 回答 2

17

在 Go 运行时中,可变参数函数的实现就像它在末尾有一个额外的切片参数而不是可变参数一样。

例如:

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反正的副本。Go 的精神是尽可能小,但仍然有用。像这样的小功能被丢弃了。您可能会为这种语法糖争论不休,因为它可以比直接的append.

请注意,扩展切片...并不会创建底层数组的副本以用作参数。参数只是给变量起别名。换句话说,它真的很有效。

于 2013-09-22T22:05:06.513 回答
10

你可以这样做:

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,您需要传递 a[]int...int's 作为参数。不要不能混合int[]int...

于 2013-09-22T18:12:03.590 回答