In Go krijgen variabelen die zonder expliciete initialisator zijn gedeclareerd automatisch zogenaamde nulwaarden (zero values), die verschillen voor verschillende types:
int — 0bool — falsestring — ""Dit is handig (geen rommel in het geheugen), maar kan gevaarlijk zijn: voor sommige types, zoals slices en kaarten, kan het werken met een nil-waarde leiden tot paniek of bugs.
Voorbeeld:
var m map[string]int m["key"] = 1 // panic: betekenisgeving aan een item in nil map var s []int fmt.Println(s, s == nil) // [] true (je kunt elementen toevoegen, maar niet met indexen benaderen)
Wat is het verschil tussen de nil-waarde van een slice en de nil-waarde van een map/kanaal, en welke bugs leidt dat tot?
Het juiste antwoord: Een slice met een nil-waarde kan veilig worden doorgegeven aan functies, worden gebruikt in append en range — dit is veilig, maar werken met een nil-map leidt tot paniek bij het proberen om iets te schrijven (maar lezen is toegestaan en geeft de zero value terug).
Voorbeeld:
var m map[string]int fmt.Println(m["no_key"]) // 0 — veilig m["key"] = 1 // panic! var s []int s = append(s, 42) // ok
Verhaal
Beschrijving: In een groot project werden niet-geïnitieerd kaarten gebruikt voor data-agregatie. Bij de eerste opname viel de applicatie consequent om van de paniek. Het probleem werd ontdekt in productie, toen een nieuwe statistiek werd ingevoerd.
Verhaal
Beschrijving: De service serialiseerde een niet-geïnitieerd slice en stuurde deze als JSON in een API-antwoord. In plaats van
[]kregen klantennull— we moesten het front-end-schema wijzigen om beide varianten te verwerken.
Verhaal
Beschrijving: In de caching-module werden nil maps onjuist vergeleken met lege maps en daardoor werd onjuist bepaald of er elementen waren. Dit leidde tot onnodige aanvragen naar de database, wat de prestaties verlaagde.