ProgrammatieBackend ontwikkelaar

Hoe werkt de embedded structs in Go? Wat is het verschil tussen embedding en normale inclusie in een structuur? Welke details moet je in overweging nemen?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

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:

  • Bij embedding zijn methoden en velden direct toegankelijk in de nieuwe structuur,
  • Bij normale inclusie moeten ze benaderd worden via de naam van het veld.

Vrag met een valkuil

"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:

  • Als de namen overeenkomen, zal het externe niveau worden gebruikt, en het interne kan worden benaderd met de naam van de embedded structuur.

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

Voorbeelden van echte fouten door gebrek aan kennis van de details van dit onderwerp


Verhaal

In een project werd een standaardstructuur voor logging geëmbeed, en daarna werd het veld Logger gedefinieerd in het afgeleide type. Als gevolg hiervan werkten aanroepen d.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.