关于go:Golang追加()什么时候创建一个新切片?

When does Golang append() create a new slice?

根据内置API文档,当原始切片的容量不够大时,append()将重新分配并复制到新的数组块。

这里是一个(简化版)递归算法,用于创建字母组合(在本例中是布尔值)。字母表的成员(真、假)递归地添加到一个切片中,直到它的长度正确为止,此时它将通过通道发送。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

import (
   "fmt"
)

func AddOption(c chan []bool, combo []bool, length int) {
    if length == 0 {
        fmt.Println(combo,"!")
        c <- combo
        return
    }
    var newCombo []bool
    for _, ch := range []bool{true, false} {
        newCombo = append(combo, ch)
        AddOption(c, newCombo, length-1)
    }
}

func main() {
    c := make(chan []bool)
    go func(c chan []bool) {
        defer close(c)
        AddOption(c, []bool{}, 4)
    }(c)
    for combination := range c {
        fmt.Println(combination)
    }
}

这里是这个代码的操场链接。在输出中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[true true true true] !
[true true true false] !
[true true true false]
[true true true false]
[true true false true] !
[true true false false] !
[true true false false]
[true true false false]
[true false true true] !
[true false true false] !
[true false true false]
[true false true false]
[true false false true] !
[true false false false] !
[true false false false]
[true false false false]
[false true true true] !
[false true true false] !
[false true true false]
[false true true false]
[false true false true] !
[false true false false] !
[false true false false]
[false true false false]
[false false true true] !
[false false true false] !
[false false true false]
[false false true false]
[false false false true] !
[false false false false] !
[false false false false]
[false false false false]

以感叹号结尾的行是从addoption发送到通道的行。没有的是出现在另一边的东西(即在main()中)。很明显,通过通道发送的切片在发送后会被更改。

由于addoption在发送切片后立即返回,因此修改必须来自代码块

1
2
3
4
5
var newCombo []bool
for _, ch := range []bool{true, false} {
    newCombo = append(combo, ch)
    AddOption(c, newCombo, length-1)
}

但是,根据文档,append()应该返回一个新的切片(cap(combo)不够大)。根据这个答案,发送到addoption的切片描述符应该是一个副本;这不是真的吗?据我所知,作为addOption()的第二个参数发送的值要么是指向切片描述符的指针,要么是append()没有返回新切片。


(P)When EDOCX1 plogenic 0 create s a new slice,it doesn't create a slice that's just one larger than the slice before.它实际上创造了一个Slice,它比以前任何一个都大。请看这本法典:(p)字母名称(P)playground(p)(P)If you run this code,you see that the capacity initially double on every allocation;this strategy is of course changed for larger slice sizes.(p)


(P)You are confusing slice,the data type,with the actual representation.The Slice descriptor is composed of a pair of ints,one for len and one for cap,and a point to the underlying data.(p)(P)So,what append returns is indeed a new slice and what is passed to add option is indeed a copy of the slice descriptor.但是,从描述者到数据,观点的价值(对了解数据的问题)是相同的。(p)(P)Edit:here is a code snippet to illustrate my point:(p)字母名称(P)如果你跑了,你会得到:(p)字母名称(P)Because since EDOCX1 plography 1 common still has capacity,both EDOCX1 commercial 2 and EDOCX1 commercial 3 share the same data ptr.If you change the capacity to 4,it prints:(p)字母名称


(P)Ref:http://criticalindirection.com/2016/02/17/slice-with-a-pinch-of-salt/(p)(P)According to the link:(p)布尔奇1(P)This is quite different from the behavior of slices in other languages:(p)布尔奇1(P)The output of example mentioned,explains the behavior.(p)字母名称布尔奇1(P)Having multiple slices pointing to same underlying array,with frequent EDOCX1 plus 4-operations can get tricky.More on this in the link above.(p)