在Go的slice tricks wiki和Go库(例如,this example)上,您有时会看到如下代码,将一个切片复制到新的支持数组中.
// In a library at the end of a function perhaps...
return append(whateverSlice[:0:0], whateverSlice...)
// In an assignment, as in the wiki example...
b = append(a[:0:0], a...)
以下是我认为我理解的内容:
- 作为
append
的第二个参数的切片中的所有项都被复制到新的支持数组中. - 在将第一个参数设置为
append
时,代码使用a full slice expression.(我们可以将第一个参数重写为a[0:0:0]
,但如果省略,将提供第一个0
.我认为这与这里更广泛的含义无关.) - 基于the spec,生成的切片应该与原始切片具有相同的类型,并且其长度和容量应该为零.
- (同样,不直接相关,但我知道你可以用
copy
而不是append
,而且读起来要清楚得多.)
然而,我仍然不能完全理解why语法append(someSlice[:0:0], someSlice...)
创建一个新的后备array.我最初也很困惑,为什么append
操作没有扰乱(或截断)原始切片.
现在让我来猜一猜:
- 我假设所有这些都是必要的和有用的,因为如果您只分配
newSlice := oldSlice
,那么对一个的更改将反映在另一个中.通常,你不会想要这样的. - 因为我们不将
append
的结果赋给原始切片(这在围棋中是正常的),所以原始切片不会发生任何变化.它不会以任何方式被截断或更改. - 因为
anySlice[:0:0]
的长度和容量都是零,所以如果要将anySlice
的元素赋给结果,GO必须创建一个新的支持array.这why是一个新的后备数组被创建吗? - 如果
anySlice...
没有元素,会发生什么?snippet on the Go Playground表示,如果您在空切片上使用此追加技巧,则副本和原始切片最初具有相同的支持array.(Edit:作为a commenter explains,我误解了这段代码.该代码片段显示,这两个项目最初是相同的,但却是neither has a backing array yet.它们最初都指向一个通用的零值.)因为这两个片的长度和容量都是零,所以只要您向其中一个片添加任何东西,that one就会得到一个新的支持array.因此,我想,效果仍然是一样的.也就是说,在append
复制之后,两个切片不能相互影响. - 这other playground snippet表明,如果一个切片具有多于零个元素,则
append
复制方法立即导致新的支持array.在这种情况下,可以说,产生的两个切片立即分离.
我可能对此担心得太多了,但我希望能更全面地解释why和append(a[:0:0], a...)
的诀窍是如何起作用的.