据我所知,“...”表示下面代码片段中数组的长度。
var days := [...]string { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }
另一方面,正如我猜测的那样,“...”意味着将切片
y
解压到下面代码片段中的 int 参数。我对此不太确定。
x := []int{1,2,3}
y := []int{4,5,6}
x = append(x, y...)
现在,两种含义的差异让我很难理解“...”是什么。
您已经注意到 Go 中
...
的两种情况。其实有3个:
[...]int{1,2,3}
在编译时将 计算为 [3]int{1,2,3}
a := make([]int, 500)
SomeVariadicFunc(a...)
将
a
解压为函数的参数。这与您错过的可变参数定义相匹配:
func SomeVariadicFunc(a ...int)
现在进一步的问题(来自OP的评论)——
为什么......在所有这些情况下都可以在语义上工作?答案是,在英语(和其他语言)中,这被称为“省略号”。从那篇文章 Ellipsis(复数省略号;源自古希腊语:ἔλλειψις, élleipsis,“遗漏”或“未达标”)是一系列点, 通常表示故意省略单词、句子或 文本的整个部分而不改变其原始含义。
1根据其上下文和在句子中的位置,省略号可以 也表示未完成的想法、主要陈述、轻微的 停顿,以及紧张或尴尬的沉默。在可变参数情况下,它使用相同的含义,但不同。它还带有“未完成的想法”的暗示。我们经常使用“...”来表示“等等”。 “我要去买面包、鸡蛋、牛奶……”在这种情况下,“……”表示“类似于面包、鸡蛋和牛奶的其他东西”。例如,
append
a[0]...
甚至
a[0], a[1], a[2]...
但这会导致空切片出现明显的问题(它确实与
...
语法一起使用),更不用说冗长了。
一般来说,“...”用来表示“许多事情”,这样它的两种用法都是有意义的。许多数组元素,许多切片元素(虽然一个是创建,另一个是调用)。我想隐藏的问题是“这是好的语言设计吗?”一方面,一旦你了解了语法,它对于大多数以英语为母语的人来说都是完全有意义的,所以从这个意义上说它是成功的。另一方面,不以这种方式重载符号是有价值的。我可能会选择不同的符号来进行数组解包,但我不能责怪他们使用了语言设计者可能直观的符号。特别是因为数组版本甚至不经常使用。
如上所述,这对编译器来说不是问题,因为案例永远不会重叠。你永远不可能让
[...]
(旁白:我省略了 Go 中它的另一种用法,因为它不在语言本身中,而是在构建工具中。输入类似
go test ./...
仅供参考,
not
意味着“解压”输入
s
。
相反,“绕过”会更合适。如果
s
s := []string{"a", "b", "c"}
,
myfunc(s...)
不等于
myfunc(s[0], s[1], s[2])
。
这个简单的代码显示了它。
func Greeting(prefix string, who ...string)
如果最后一个参数可分配给切片类型 []T 并且是 后跟...
,它作为 ...T 的值不变地传递 范围。在这种情况下,不会创建新切片。
给定切片 s 并调用
s := []string{"James", "Jasmine"}
Greeting("goodbye:", s...)
在 Greeting 中,who
将与 s 具有相同的值,并且具有相同的基础 数组。 如果它“解压”输入参数,则应创建一个具有 different 数组的新切片(事实并非如此)。
注意:这不是真正的“绕过”,因为切片本身(而不是底层数组)被复制到函数中(Go 中没有“引用”)。但是,函数中的切片指向相同的原始底层数组,因此它是比“解包”更好的描述。