在可变函数中混合"爆炸"切​​片和常规参数

pau*_*kul 11 go slice

我想知道为什么不可能在go中执行以下操作:

func main() {
    stuff := []string{"baz", "bla"}
    foo("bar", stuff...)
}

func foo(s ...string) {
    fmt.Println(s)
}
Run Code Online (Sandbox Code Playgroud)

根据我的理解,切片......"爆炸"切​​片,以便它可以用于多参数函数调用.所以上面的例子实际上应该扩展到foo("bar", "baz", "bla").

foo(stuff...) 按预期工作,这里没有惊喜,但在上面的例子中,编译器抱怨过多的参数.

这是一个理想的限制吗?我来自一个foo("bar", *stuff)非常好的红宝石背景(并且,至少在我的书中,同样的事情),这就是为什么这让我感到惊讶.

mvn*_*aai 13

让它工作的丑陋方法是将它变成一个新的可变参数。

foo(append([]string{"bar"}, stuff...)...)
Run Code Online (Sandbox Code Playgroud)

如果顺序无关紧要:

foo(append(stuff, "bar")...)
Run Code Online (Sandbox Code Playgroud)

https://play.golang.org/p/mY6y0vScfPB


icz*_*cza 10

可变参数的值可以通过枚举元素使用由其名称后跟的指定的现有切片来指定....

您希望混合Go语言规范不允许的两种可能方式(...参数传递给参数).

如果使用第一个表单(枚举元素):

传递的值[作为variadic参数]是一个新的类型切片,[]T带有一个新的底层数组,其连续元素是实际参数.

如果使用后者(传递现有切片后跟...),则不会创建新切片,您传递的切片将按原样使用.而通过分片只能用于指定的值一个 -在最后 -可变参数的参数.尝试传递单个元素切片将与您的函数的签名(在本例中为参数列表)不匹配,您将收到错误:

too many arguments in call to foo
Run Code Online (Sandbox Code Playgroud)

Go中没有涉及实际的"爆炸",该术语仅用于其他语言,以帮助可视化传递的数组或切片不是可变参数的元素,但将是variadic参数本身的值.

混合2将需要分配新切片,因为显然不能使用现有切片.


Von*_*onC 5

关于这个的规范是在" 传递参数的...参数 "中:

如果f是具有p类型的最终参数的可变参数...T,则在f类型内p等效于类型[]T.
如果f在没有实际参数的情况下调用p,则传递给的p值为nil.
否则,传递的值是一个新的类型切片,[]T其中包含一个新的基础数组,其连续元素是实际参数,所有这些都必须可分配给它们T.

在你的情况下,东西......工作:

如果最终参数可分配给切片类型[]T,则可以将其作为...T参数的值(如果参数后跟参数)保持不变....在这种情况下,不会创建新切片.

"bar", stuff...不符合上述任何一种情况.

T, []T不匹配f([]T).