Il problema è semplice: si dispone di una fetta di driver
s:
var Drivers []driver
noti che Drivers
è una porzione di qualche tipo di struct, non una porzione di puntatori!
Quando si aggiunge qualcosa (o si assegna un valore ad uno dei suoi elementi):
Drivers = append(Drivers, driver)
che fa una copia del valore aggiunto (o assegnati)! Quindi, quando si esegue questa operazione in seguito:
driver.variables = make(map[string]string)
Sarà impostato un nuovo valore di mappa per driver.variables
, ma che è distinto dal valore memorizzato in Drivers
(più precisamente a Drivers[0]
).
Successivamente si popola driver.variables
, ma si stampa Drivers[0].variables
. Sono 2 diversi valori di struttura, con 2 valori di mappa diversi. Le goroutine non hanno un ruolo qui (sono correttamente sincronizzate quindi non dovrebbero comunque).
Vuoi stampare driver.variables
:
fmt.Print(driver.variables)
vedreste (provate sul Go Playground):
map[a:b]
Se si commenta questa riga:
driver.variables = make(map[string]string) // Commenting this line makes it work, too
Funzionerebbe, ma solo perché pur avendo 2 valori struct, hanno lo stesso valore di mappa (stessa intestazione della mappa che punta alla stessa struttura dati della mappa).
Si può anche farlo funzionare se si chiama driver.populate()
sul valore struct Drivers[0]
(e attaccare alla stampa Drivers[0].variables
):
go Drivers[0].populate(done)
// ...
fmt.Print(Drivers[0].variables)
provare questo uno sul Go Playground.
E si può anche farlo funzionare se Drivers
è una fetta di puntatori:
var Drivers []*driver
// ...
driver := &driver{
variables: make(map[string]string),
}
Perché driver
e Driver[0]
sarà lo stesso puntatore (si avrà solo un valore struct e un valore mappa come l'iniziale la mappa non è più accessibile). Prova questo su Go Playground.
Questa è la risposta corretta: le goroutine in questo caso sono irrilevanti: https://play.golang.org/p/Eh3gPbFWPL mostra il problema con solo la goroutine principale; capendo che le strutture sono _copiate_, ma i puntatori (e i tipi di riferimento, come la mappa) sono condivisi è ciò che sta causando il problema qui. – val