简体   繁体   English

Go:Variadic函数和太多参数?

[英]Go: Variadic function and too many arguments?

Here's an example of the problem I'm having: 这是我遇到的问题的一个例子:

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...)
}

When I run this I get the error too many arguments in call to foo . 当我运行这个时,我too many arguments in call to foo得到的错误too many arguments in call to foo I guess I could understand why this is happening, but what's not clear to me is how I can get around it without having to make a copy of b with an extra slot at the beginning for aa (which I'd rather not do, as this code would be running quite often and with b being somewhat long). 我想我能理解为什么会发生这种情况,但我不清楚的是我怎么能绕过它而不必在开头为aa制作一个带有额外插槽的b副本(我宁愿不这样做,因为这段代码会经常运行,并且b有点长)。

So my question is: Am I just doing this wrong? 所以我的问题是:我只是做错了吗? And if not, what would be the most efficient way to do what I'm trying to do? 如果没有,那么做我想做的事情最有效的方法是什么?

(Also, I can't change the signature of foo ). (另外,我无法改变foo的签名)。

In the Go runtime a variadic function is implemented as if it had an extra slice parameter at the end instead of a variadic parameter. 在Go运行时一个可变参数函数的实现 ,如果它已经在最后,而不是可变参数参数的额外片参数。

For example: 例如:

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)

In theory Go could handle the case where some of a variadic arguments are specified directly and the rest are expanded out of an array/slice. 从理论上讲,Go可以处理直接指定一些可变参数的情况,其余参数从数组/切片中扩展出来。 But, it would not be efficient. 但是,它效率不高。

//This call
Foo(5, c, b...)

// would be implemented like this.
v := append([]int{c},b...)
FooImpl(5, v)

You can see that Go would be creating a copy of b anyways. 你可以看到Go无论如何都会创建一个b的副本。 The ethos of Go is to be as small as possible and yet still useful . Go的精神是尽可能小,但仍然有用 So small features like this get dropped. 所以像这样的小功能会被丢弃。 You may be able to argue for this syntactic sugar, as it can be implemented slightly more efficiently than straight forward approach of append . 你或许可以争论这种语法糖,因为它可以比直接的append方法更有效地实施。

Note that expanding a slice with ... does not create a copy of the underlying array for use as the parameter. 请注意, 使用...扩展切片不会创建基础数组的副本以用作参数。 The parameter just aliases the variable. 该参数只是变量的别名。 In other words it's really efficient. 换句话说,它真的很有效率。

You can do something like this: 你可以这样做:

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...)...)
}

When expecting b ...int , you need to pass a []int... or int 's as parameters. 当期望b ...int ,你需要传递一个[]int...int作为参数。 Don't can't mix int and []int... 不要混用int[]int...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM