ProgrammierungBackend Entwickler

Beschreiben Sie die Besonderheiten der Arbeit mit Zeigern (Pointers) in Go: wann man sie verwenden sollte, wie sie sich von Referenzen in anderen Sprachen unterscheiden und welche typischen Fallen bei ihrer Anwendung auftreten können?

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

Antwort.

In Go ist ein Zeiger eine Variable, die die Adresse einer anderen Variable speichert. Im Gegensatz zu einigen Sprachen ist es in Go nicht möglich, Zeigerarithmetik durchzuführen, was sie sicherer macht. Zeiger werden in Go häufig verwendet für:

  • Übertragung großer Strukturen an Funktionen (um Kopien zu vermeiden).
  • Änderung eines Objekts aus einer externen Funktion.
  • Umsetzung komplexer Datenstrukturen (z. B. Listen, Bäume).

In Go fehlt die explizite Unterstützung für Referenztypen, wie zum Beispiel in C++, jedoch sind Slices und Maps aufgrund ihrer Natur bereits referenziell und werden oft per Wert übergeben.

Beispiel für die Übertragung eines Zeigers und eines Wertes:

package main import "fmt" type User struct { Name string } func changeNameByValue(u User) { u.Name = "Vasya" } func changeNameByPointer(u *User) { u.Name = "Petya" } func main() { user := User{Name: "Ivan"} changeNameByValue(user) fmt.Println(user.Name) // Ivan changeNameByPointer(&user) fmt.Println(user.Name) // Petya }

Fangfrage.

Können Zeiger in Go auf Konstanten oder Literale zeigen?

Korrekte Antwort: Nein, in Go kann man nicht direkt eine Adresse von einer Konstante oder einem Literal nehmen. Eine Adresse kann nur von einer Variablen genommen werden:

x := 5 p := &x // OK p2 := &10 // Kompilierungsfehler

Dies führt oft zu Verwirrungen mit Sprachen, in denen dies zulässig ist.

Beispiele für reale Fehler aufgrund mangelnden Wissens über die Feinheiten des Themas.


Geschichte

In einem Projekt versuchte ein Entwickler, einen Verweis auf ein Element eines Slices zu übergeben, in der Annahme, dass er das Slice sicher über den Zeiger modifizieren könnte. Er irrte sich: Das Slice selbst enthält einen Zeiger, aber nach append() ändert sich die Adresse des zugrunde liegenden Arrays und die Änderungen spiegelten sich nicht immer in den Originaldaten wider. Dies führte zu schwer fassbaren Bugs (Daten "gingen verloren").


Geschichte

In dem Projekt wurde eine Liste von Zeigern auf lokale Variablen in einer Schleife erstellt, und nach Verlassen der Schleife zeigten alle Zeiger auf dieselbe Variable (die durchlaufene Schleifenvariable). Der Fehler wurde erst nach einem Absturz in der Produktion bemerkt.


Geschichte

Der Entwickler ging fälschlicherweise davon aus, dass die Zuweisung eines Zeigers das vorherige Objekt aus dem Speicher freigibt und wies den Zeiger ausdrücklich auf nil zu, in der Erwartung, dass der GC sofort reagiert. In der Praxis entscheidet der Garbage Collector in Go selbst, wann Objekte bereinigt werden, dabei ignoriert er vorzeitige Nullsetzungen von Referenzen. Dies führte zu Speicherlecks, wo man mit einer zeitgerechten Freigabe des Speichers rechnete.