根据内置 API 文档,append()会在原切片容量不够大时重新分配并复制到新的数组块中。
这是一个用于创建字母表(在本例中为布尔值)组合的递归算法(简化版本)。字母表的成员(true、false)被递归地添加到切片中,直到达到正确的长度,此时它会通过通道发送。
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)
}
}
Here是此代码的游乐场链接。在输出中:
[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 在发送切片后立即返回,因此修改必须来自代码块
var newCombo []bool
for _, ch := range []bool{true, false} {
newCombo = append(combo, ch)
AddOption(c, newCombo, length-1)
}
但是,根据文档,append() 应该返回一个新切片(cap(combo) 不够大)。根据这个答案,发送给AddOption的切片描述符应该是一个副本;这不是真的吗?据我所知,作为 AddOption() 的第二个参数发送的值要么是指向切片描述符的指针,要么append() 不返回新切片。