In Go is embedding een mechanisme waarmee je het gedrag van een structuur kunt "erfgen" door een structuur in een andere te embedden zonder expliciete overerving, zoals bijvoorbeeld in OOP. De embedded structuur wordt anonieme velden van de nieuwe structuur.
Alle methoden van de embedded structuur worden methoden van de nieuwe structuur alsof ze "geërfd" zijn.
Voorbeeld:
package main import "fmt" type Animal struct { Name string } func (a Animal) Speak() { fmt.Println("Mijn naam is", a.Name) } type Dog struct { Animal // embedding, anoniem veld Breed string } func main() { d := Dog{ Animal: Animal{Name: "Rex"}, Breed: "Shepherd", } d.Speak() // Geërfde methode! fmt.Println(d.Name) // Veld is direct toegankelijk }
Het belangrijkste verschil tussen embedding en normale inclusie van een structuur als benoemd veld:
"Als de embedded structuur en de externe structuren velden met dezelfde naam bevatten, welke zal dan worden gebruikt en hoe kun je er toegang toe krijgen?"
Veel mensen denken dat alleen het "bovenste" veld zal worden gebruikt, maar dat werkt anders:
Voorbeeld:
type Base struct { Name string } type Child struct { Base // embedding Name string // overeenkomend veld } c := Child{Base: Base{Name: "Base"}, Name: "Child"} fmt.Println(c.Name) // Child fmt.Println(c.Base.Name) // Base
Verhaal
In een project werd een standaardstructuur voor logging geëmbeed, en daarna werd het veld
Loggergedefinieerd in het afgeleide type. Als gevolg hiervan werkten aanroepend.Logger.Info()niet zoals verwacht, omdat de toegang tot het embedded veld "verloren" ging tussen de gelijknamige.
Verhaal
Een ontwikkelaar probeerde een methode in de afgeleide structuur te overschrijven, maar methoden worden niet "overschreven" - er verschijnt simpelweg een nieuwe, en de ouder blijft toegankelijk als
Child.Base.Method(). Dit leidde ertoe dat een deel van de code de "oude" versie van de methode gebruikte, wat een andere logica verwachtte.
Verhaal
Bij het serialiseren van JSON met embedded structuren ontstonden er verrassingen: de velden van de "embedded" structuur verschenen in het rootobject. Vanwege het gebrek aan kennis over hoe embedding invloed heeft op marshaling, werd de structuur onjuist geserialiseerd, wat de achterwaartse compatibiliteit van de API verstoorde.