ProgrammierungBackend Entwickler

Wie funktioniert die Einbettung von Strukturen (embedding structs) in Go? Was unterscheidet die Einbettung von der normalen Einfügung in eine Struktur? Welche Feinheiten sind zu beachten?

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

Antwort

In Go ist Embedding der Mechanismus, der es ermöglicht, das Verhalten einer Struktur durch das Einbetten einer Struktur in eine andere zu "erben", ohne eine explizite Vererbung zu verwenden, wie zum Beispiel in der OOP. Die eingebettete Struktur wird zu den Feldern der neuen Struktur (anonyme Felder).

Dabei werden alle Methoden der eingebetteten Struktur zu den Methoden der neuen Struktur, als ob sie "vererbt" wurden.

Beispiel:

package main import "fmt" type Animal struct { Name string } func (a Animal) Speak() { fmt.Println("Mein Name ist", a.Name) } type Dog struct { Animal // Einbettung, anonymes Feld Breed string } func main() { d := Dog{ Animal: Animal{Name: "Rex"}, Breed: "Shepherd", } d.Speak() // Vererbte Methode! fmt.Println(d.Name) // Feld direkt verfügbar }

Der Hauptunterschied zwischen Einbettung und normaler Einfügung einer Struktur als benanntem Feld:

  • Bei der Einbettung sind Methoden und Felder direkt bei der neuen Struktur verfügbar,
  • Bei der normalen Einfügung müssen sie über den Feldnamen aufgerufen werden.

Fangfrage

"Wenn die eingebettete Struktur und die äußere Felder mit demselben Namen enthalten, welches wird verwendet und wie kann man darauf zugreifen?"

Viele glauben, dass nur das "obere" Feld verwendet wird, aber es funktioniert anders:

  • Wenn die Namen übereinstimmen, wird die äußere Ebene verwendet, und auf die innere kann über den Namen der eingebetteten Struktur zugegriffen werden.

Beispiel:

type Base struct { Name string } type Child struct { Base // Einbettung Name string // übereinstimmendes Feld } c := Child{Base: Base{Name: "Base"}, Name: "Child"} fmt.Println(c.Name) // Child fmt.Println(c.Base.Name) // Base

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


Geschichte

In einem Projekt wurde eine Standardstruktur für das Logging eingebettet, und anschließend wurde ein Feld Logger im Kindtyp definiert. Infolgedessen funktionierten Aufrufe wie d.Logger.Info() nicht wie erwartet, da der Zugriff auf das eingebettete Feld "verloren ging" zwischen den gleichnamigen.


Geschichte

Der Entwickler versuchte, eine Methode in der Kindstruktur zu überschreiben, aber Methoden werden nicht "überschrieben" – es erscheint einfach eine neue, und die Elternmethode bleibt weiterhin über Child.Base.Method() verfügbar. Dies führte dazu, dass ein Teil des Codes die "alte" Version der Methode verwendete, wobei eine andere Logik erwartet wurde.


Geschichte

Bei der Serialisierung von JSON mit eingebetteten Strukturen gab es Überraschungen: Die Felder der "eingebetteten" Struktur tauchten im Stammobjekt auf. Aufgrund mangelnden Wissens über die Auswirkungen von Einbettung auf das Marshaling wurde die Struktur inkorrekt serialisiert, was die Abwärtskompatibilität der API beeinträchtigte.