In base allo builtin api docs, append() verrà riallocato e copiato in un nuovo blocco di matrice quando la capacità della sezione originale non è sufficientemente grande.Quando Golang append() crea una nuova fetta?
Ecco una (versione semplificata di) un algoritmo ricorsivo per la creazione di combinazioni di un alfabeto (in questo caso i booleani). I membri dell'alfabeto (vero, falso) vengono aggiunti in modo ricorsivo a una sezione finché non è la lunghezza corretta, a quel punto viene inviata sul canale.
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 è il campo di gioco per questo codice. Nell'output:
[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]
Le righe che terminano con un punto esclamativo sono quelle inviate nel canale da AddOption. Quelli senza sono ciò che emerge dall'altra parte (cioè in main()). È chiaro che le slice inviate sul canale vengono cambiate dopo che sono state inviate.
Dal AddOption ritorna immediatamente dopo l'invio la fetta, la modifica deve venire dal blocco di codice
var newCombo []bool
for _, ch := range []bool{true, false} {
newCombo = append(combo, ch)
AddOption(c, newCombo, length-1)
}
Ma, secondo la documentazione, aggiungere() dovrebbe restituire una nuova fetta (cap (combinata) è non abbastanza grande). Secondo this answer, il descrittore di slice inviato a AddOption dovrebbe essere una copia; non è vero? Per quanto posso dire, il valore inviato come secondo argomento di AddOption() è o un puntatore a un descrittore di sezione o append() non restituisce una nuova porzione.
http://blog.golang.org/go-slices-usage-and-internals e http://blog.golang.org/slices potrebbero essere pertinenti alla tua domanda. – dyoo
Vedere anche http://stackoverflow.com/questions/17332227/big-o-of-append-in-golang – nos