【问题标题】:mixing "exploded" slices and regular parameters in variadic functions在可变参数函数中混合“爆炸”切​​片和常规参数
【发布时间】:2015-04-21 22:18:12
【问题描述】:

我想知道为什么不能在 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) 非常好(至少在我的书中,同样的事情),这就是为什么这让我感到惊讶。

【问题讨论】:

    标签: go slice


    【解决方案1】:

    这方面的规范在“Passing arguments to ... parameters”:

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

    在你的情况下,东西......在哪里起作用:

    如果最后一个参数可分配给切片类型[]T,如果参数后跟...,则它可以作为...T 参数的值原封不动地传递。在这种情况下,不会创建新切片。

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

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

    【讨论】:

      【解决方案2】:

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

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

      如果使用第一种形式(枚举元素):

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

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

      too many arguments in call to foo
      

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

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

      【讨论】:

        【解决方案3】:

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

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

        如果顺序无关紧要:

        foo(append(stuff, "bar")...)
        

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

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            猜你喜欢
            • 2018-12-10
            • 2014-01-26
            • 2019-08-21
            • 2013-02-08
            • 1970-01-01
            • 2014-02-01
            • 2013-03-20
            • 1970-01-01
            • 2019-02-05
            相关资源
            最近更新 更多