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

时间:2015-02-20 09:26:43

标签: go slice

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

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

func foo(s ...string) {
    fmt.Println(s)
}

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

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

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

4 个答案:

答案 0 :(得分:9)

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

您希望混合使用Go语言规范(Passing arguments to ... parameters)不允许的两种可能方式。

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

  

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

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

too many arguments in call to foo

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

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

答案 1 :(得分:5)

关于此的规范在" Passing arguments to ... parameters":

  

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

在你的情况下,哪些东西......有效:

  

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

但是"bar", stuff...与上面指定的任何一种情况都不匹配。

T, []Tf([]T)不匹配。

答案 2 :(得分:1)

让它发挥作用的丑陋方法是将其变成一种新的变量。

foo(append([]string{"bar"}, stuff...)...)

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

答案 3 :(得分:1)

我在准备参数以提供给外部命令时遇到了这种情况。 如果可能,只需构建一个单参数切片,那么您就不必担心 在调用函数时将标量与切片组合:

package main
import "os/exec"

func main() {
   stuff := []string{"bar"}
   stuff = append(stuff, "baz", "bla")
   exec.Command("name", stuff...).Run()
}