Reputation: 2304
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
. 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).
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
).
Upvotes: 18
Views: 10140
Reputation: 59347
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.
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. 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. The ethos of Go is to be as small as possible and yet still useful. 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
.
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.
Upvotes: 20
Reputation: 121792
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. Don't can't mix int
and []int...
Upvotes: 12