某些语言(C、Python...)接受可变参数。基本上,您允许函数的客户端传递a number参数,但未指定数量。由于函数仍然需要以某种方式处理这些参数,因此它们通常会转换为某种类型的集合。例如,在 Python 中:
def foo(x, *args): # * is used for variadic arguments
return len(args)
>>> foo(1) # Passed the required argument, but no varargs
0
>>> foo(1, 2, 3) # Passed the required, plus two variadic arguments
2
>>> foo(1, 2, 3, 4, 5, 6) # required + 5 args, etc...
5
现在这种方法的一个明显问题是一些论点就类型而言,这是一个相当模糊的概念。 C 使用指针,Python 一开始并不真正关心类型,而 Go 决定将其限制为指定的情况:你通过给定类型的切片 https://golang.org/ref/spec#Passing_arguments_to_..._parameters.
这很好,因为它让类型系统做它的事情,同时仍然非常灵活(特别是,所讨论的类型可以是一个接口,因此只要函数知道如何处理,您就可以传递不同的“实际类型”这些。
典型的例子是命令功能 https://golang.org/pkg/os/exec/#Command,执行一个程序,传递它一些论点:
func Command(name string, arg ...string) *Cmd
这里很有意义,但请记住,可变参数只是一个传递切片的便捷方式。您可以使用完全相同的 API:
func Command(name string, args []string) *Cmd
第一个的唯一优点是它允许您传递无参数、一个参数、多个参数......而无需自己构建切片。
那你的问题呢?
有时,你do有一个切片,但需要调用可变参数函数。但如果你天真地这样做:
my_args_slice := []string{"foo", "bar"}
cmd := Command("myprogram", my_args_slice)
编译器会抱怨它需要字符串,但得到的是切片!你想告诉它的是,它不必“在后面构建切片”,因为你已经有了一个切片。您可以使用以下省略号来做到这一点:
my_args_slice := []string{"foo", "bar"}
cmd := Command("myprogram", my_args_slice...) // <- Interpret that as strings
The append
功能,尽管是内置的且特殊的,遵循相同的规则 https://golang.org/ref/spec#Appending_and_copying_slices。您可以将零个、一个或多个元素附加到切片。如果您想连接切片(即您已经有一个“参数切片”),您可以类似地使用省略号以使其直接使用它。