for i := 0; i < 12; i++ {
i := i
...
Pazzo come sembra, questo è qualcosa che vedrai nel codice Go. Deriva dal modo in cui funzionano le chiusure e dal modo in cui le variabili sono esaminate. La tua funzione anonima è una chiusura che cattura i. Specificamente, sta catturando una variabile chiamata i, non il valore corrente di i, e cattura qualunque cosa sia in ambito. Nel codice originale questa è la variabile loop, che è la stessa variabile per ogni iterazione del ciclo. Tutte le tue chiusure hanno catturato la stessa variabile. L'aggiunta di i := i
dichiara una nuova variabile per ogni iterazione. Ora ogni chiusura catturerà questa nuova variabile e ad ogni iterazione sarà una variabile diversa.
In maggiore dettaglio, l'ambito della variabile di ciclo i è for. Ciò include il blocco del ciclo, ma poiché la dichiarazione della variabile di ciclo i è esterna al blocco, la dichiarazione di una nuova variabile con lo stesso nome all'interno del blocco è legale e crea una nuova variabile in quel punto nel blocco. La variabile di loop viene quindi ombreggiata. Spesso una variabile dichiarata come questa va in pila, ma in questo caso l'analisi di escape del compilatore vede che la tua chiusura si riferisce ancora a questa variabile di blocco quando esce dall'oscilloscopio alla fine del blocco, e quindi la variabile è posizionata sul mucchio. Ad ogni iterazione, il blocco viene reinserito e una nuova variabile i viene posizionata nell'heap.
Risolto anche in [le FAQ] (http://golang.org/doc/go_faq.html#closures_and_goroutines). – kostix