Goroutine-Verhalten: Das Rätsel lösen
Wir stoßen auf ein verwirrendes Verhalten im bereitgestellten Go-Code:
package main import ( "fmt" "time" ) type field struct { name string } func (p *field) print() { fmt.Println(p.name) } func main() { data := []field{{"one"}, {"two"}, {"three"}} for _, v := range data { go v.print() } <-time.After(1 * time.Second) }
Es stellt sich die Frage: Warum gibt dieser Code durchgehend dreimal „drei“ aus, anstatt „eins“, „zwei“ und „drei“ in jedem anzuzeigen? Reihenfolge?
Das Problem verstehen
Der Kern des Problems liegt in einer subtilen Race-Bedingung, die durch die Verwendung der Bereichsvariablen v in der Goroutine-Funktion verursacht wird.
Wenn wir v.print() schreiben, übergeben wir effektiv einen Zeiger auf die Variable v, die eine Referenz auf das aktuelle Element in der Bereichsdatenschleife ist. Die Schleife iteriert jedoch weiter und ändert den Wert von v.
Wenn die Goroutine ausgeführt wird, hat sie zufällig den Endwert von v, der „drei“ ist. Dies erzeugt die unerwartete Ausgabe von drei „Dreien“.
Behebung des Problems: Mehrere Ansätze
Es gibt mehrere Möglichkeiten, dieses Problem zu lösen:
1. Verwenden einer kurzen Variablendeklaration:
Erstellen Sie eine neue Variable v mit Gültigkeitsbereich für jede Iteration der Schleife:
for _, v := range data { v := v // Short variable declaration to create a new `v`. go v.print() }
2. Verwenden eines Zeigersegments:
Ändern Sie den Datentyp in ein Zeigersegment und übergeben Sie die einzelnen Zeiger an die Goroutine-Funktion:
data := []*field{{"one"}, {"two"}, {"three"}} // Note the '*' for _, v := range data { go v.print() }
3. Verwenden der Adresse des Slice-Elements:
Nehmen Sie die Adresse jedes Slice-Elements und übergeben Sie den Zeiger an die Goroutine-Funktion:
data := []*field{{"one"}, {"two"}, {"three"}} // Note the '*' for i := range data { v := &data[i] go v.print() }
Schlussfolgerung
Denken Sie daran, dass die Übernahme von Adressen von Bereichsvariablen zu unerwartetem Verhalten in Goroutinen führen kann, wenn die Schleife den Wert der Variablen ändert. Durch die Verwendung der oben beschriebenen Techniken können wir sicherstellen, dass jede Goroutine einen eindeutigen Wert erhält, und Probleme mit dem Datenwettlauf vermeiden.
Das obige ist der detaillierte Inhalt vonWarum gibt dieser Go-Code dreimal „Three' anstelle von „One', „Two' und „Three' aus?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!