In Go is het mogelijk om waarden van elk type via kanalen te verzenden: int, struct, pointers, interfaces, enz.
Code en voorbeeld:
type Data struct { N int } c := make(chan Data) d := Data{N: 1} c <- d // de structuur wordt volledig gekopieerd p := &Data{N: 3} c2 := make(chan *Data) c2 <- p // een pointer naar hetzelfde object werd via het kanaal verzonden
Als je een structuur via een kanaal verzendt die een pointer-veld bevat — zal er een race condition optreden bij het wijzigen van dit veld aan beide zijden van het kanaal?
Antwoord:
Voorbeeld:
type Box struct { Ptr *int } x := 10 chanBox := make(chan Box) chanBox <- Box{Ptr: &x} // zowel de verzender als de ontvanger hebben toegang tot x!
Verhaal
Er waren frequente "toevallige" crashes en mysterieuze waarden in de taakstructuur in een gedistribueerde wachtrij. Het bleek dat pointers naar gemeenschappelijke structuren via het kanaal werden verzonden, die gelijktijdig in meerdere goroutines werden gewijzigd. We hebben besloten om te switchen naar het verzenden van kopieën van de gegevens.
Verhaal
Asynchrone berichtverwerking werkte met structuren die slices-pointers naar een gemeenschappelijkArray bevatten. Bij gelijktijdige verzending via het kanaal werden delen van hetzelfde geheugen vanuit verschillende plaatsen gewijzigd, wat leidde tot obscure bugs en gegevenscorruptie.
Verhaal
In de push-notificatiedienst werden er pointers naar objecten via het kanaal verzonden, die vervolgens door goroutines werden verwerkt. Bij gelijktijdige beëindiging en sluiting van het kanaal werden delen van structuren nog steeds gewijzigd, wat paniek of een data race veroorzaakte. De overgang naar het kopiëren van structuren vóór verzending hielp.