ProgrammierungGo Backend-Entwickler

Erklären Sie, wie der Range-Mechanismus in Go beim Arbeiten mit Maps und Slices funktioniert. Welche Feinheiten gibt es bei der Verwendung von Schleifenvariablen und auf welche Fehler kann man stoßen?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

Die Schleife for ... range ermöglicht es, bequem über die Elemente eines Slices, einer Map, eines Arrays oder einer Zeichenkette zu iterieren.

  • Für Slices: Bei jeder Iteration werden der Index und eine Kopie des Elements zurückgegeben.
  • Für Maps: Es werden der Schlüssel und eine Kopie des Wertes zurückgegeben.

Beispiel:

s := []int{1, 2, 3} for i, v := range s { fmt.Println(i, v) } m := map[string]int{"a":1, "b":2} for k, v := range m { fmt.Println(k, v) }

Wichtige Feinheit: Die Variablen i, v, k usw. werden in allen Iterationen wiederverwendet! Dies wird häufig zur Quelle von Bugs, wenn sie innerhalb der Schleife per Referenz übergeben oder Goroutinen innerhalb von Range gestartet werden.

Fangfrage

Was passiert, wenn man innerhalb von Range auf einem Slice eine Goroutine startet und die Iterationsvariable erfasst? Wie kann man den Fehler vermeiden?

Antwort: Es tritt ein typischer Fehler auf: Innerhalb der Goroutine werden die Schleifenvariablen verwendet, die nach Abschluss der Schleife den letzten Wert haben werden. Um dies zu vermeiden, sollte man lokale Kopien erstellen:

nums := []int{1, 2, 3} for _, v := range nums { go func(val int) { fmt.Println(val) }(v) }

Beispiele für reale Fehler aufgrund fehlender Feinheiten


Geschichte

In einem Projekt wurde Range verwendet, um einen Slice über mehrere Goroutinen zu füllen, ohne die Schleifenvariablen zu kopieren. Alle Goroutinen druckten denselben Wert aus – den letzten des Arrays, was die Geschäftslogik stark beeinträchtigte.


Geschichte

Beim Iterieren über eine Map wurde der Verweis auf den Wert in einen neuen Slice von Zeigern gespeichert. Infolgedessen verwiesen alle Elemente des neuen Slices auf dieselbe Variable – die, die in der Schleife verwendet wurde (Kopie des Wertes). Der Bug zeigte sich bei der Aktualisierung dieser Variablen außerhalb der Schleife (panic: ungültige Speicheradresse oder unerwartete Daten).


Geschichte

In einem internen Tool wurden beim Range über einen String Handler für gewichtige Teilstrings gestartet, aber für jede Iteration erhielt ich einen Offset in Bytes, nicht in Unicode-Zeichen. Ergebnis: fehlerhafte Verarbeitung für Unicode-Zeichen, fehlerhaftes Schneiden von Zeichen.