Achtergrond:
In Go komen vaak situaties voor waarin de ingebouwde typen niet voldoende zijn en het nodig is om een eigen datatype met methoden te definiëren voor het kapselen van logica en het uitbreiden van functionaliteit. Dit wordt bereikt door aangepaste typen (type) en methoden (func (r Receiver) MethodName()) te maken.
Probleem:
Beginnende ontwikkelaars raken vaak in de war — wat is het verschil tussen het declareren van een nieuw type op basis van een bestaand type? Hoe moet je methoden correct implementeren? Hoe wordt het probleem van kopiëren en doorgeven per waarde/aanwijzer opgelost? Ze maken fouten in de zichtbaarheid, receiver type en werken met embedded structs.
Oplossing:
Voor het definiëren van een eigen type wordt het sleutelwoord type gebruikt. Methoden worden geïmplementeerd met behulp van de receiver — dit is belangrijk voor het werken met interfaces.
Codevoorbeeld:
type MyInt int func (m MyInt) Double() int { return int(m) * 2 } // Voor structuren: type User struct { Name string Age int } func (u *User) Birthday() { u.Age++ } var u = User{"Alice", 30} u.Birthday() // Age = 31
Belangrijke kenmerken:
Erven aangepaste types methoden van het basis type?
Nee. Als je type MyInt int definieert, heeft MyInt geen methoden van int. Bijv. de aanroep van String() of andere methoden van het basis type zal niet werken.
Kun je methoden definiëren voor een type alias?
Voor alias (type MyType = ExistingType) kunnen geen methoden worden toegevoegd. Methoden worden alleen gedefinieerd voor nieuwe types (type MyType ExistingType), en niet voor aliassen.
Welke receiver te gebruiken: pointer of waarde?
Als de methode het object moet wijzigen, is het beter om een pointer te gebruiken. De value receiver kopieert de structuur, wat kan leiden tot onverwacht gedrag als de structuur bijvoorbeeld slices en maps bevat.
Codevoorbeeld:
type Counter struct { value int } func (c *Counter) Inc() { c.value++ } func main() { c := Counter{} c.Inc() // alleen met pointer zal de methode value wijzigen }
Een programmeur creëerde type MySlice []int en verwachtte dat de methoden van []int, zoals append, zouden werken als methoden op het type MySlice. Uiteindelijk bleek dat er geen methoden waren en was het niet mogelijk om MySlice rechtstreeks als []int aan te roepen.
Voordelen:
Nadelen:
Type Counter int werd gedefinieerd met methode Inc, waardoor het in verschillende delen van het programma kon worden gebruikt met gemeenschappelijke logica en zonder herhalende code.
Voordelen:
Nadelen: