ProgrammatieBackend ontwikkelaar

Beschrijf de kenmerken van het werken met slices in Go: wat is een nil slice, wat is het verschil tussen length en capacity, en hoe vergroot je een slice correct zonder gegevenslekken of panics?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Slice is een dynamische array, de belangrijkste datastructuur bij het werken met arrays in Go. Historisch gezien boden programmeertalen vaste arrays of zwaardere structuren aan. Go heeft slices geïmplementeerd als een handig hulpmiddel voor het verwerken van geheugenverzamelingen met automatische groottebeheer en de mogelijkheid om de lengte te wijzigen.

Probleem betreft het juiste beheer van geheugen, het omgaan met randgevallen (lege, nil, volledige slices), en het begrijpen van het verschil tussen de lengte en capaciteit van een slice.

Oplossing is het correct gebruiken van ingebouwde functies len(), cap(), en het werken met slices volgens Go-overeenkomsten.

Voorbeeldcode:

var a []int // nil slice, len=0, cap=0 b := make([]int, 0) // lege slice, len=0, cap=0 c := make([]int, 3, 5) // len=3, cap=5 c = append(c, 4, 5, 6) // cap zal automatisch toenemen

Belangrijkste kenmerken:

  • Nil slice (var s []int) reserveert helemaal geen geheugen, het verschilt intern van een lege slice (make([]int, 0)).
  • Length toont het huidige aantal elementen, capacity is het maximale zonder extra allocatie.
  • Bij append, als de capacity niet voldoende is, wordt er een nieuwe allocatie gemaakt achter de schermen en blijven de oude gegevens onveranderd.

Vragen met een valstrik.

Wat is de lengte en capaciteit van een slice na append aan een nil slice?

Een nil slice (var s []int) wordt na append(s, 1) een slice van lengte 1, capaciteit 1 — Go reserveert zelf geheugen.

var s []int s = append(s, 42) // s is nu [42], len=1, cap=1

Kan je de capacity van een nil slice aanspreken?

Ja, bij een nil slice geven beide functies — len en cap — 0 terug. Er zal geen panic zijn.

var s []int fmt.Println(len(s), cap(s)) // 0 0

Wat gebeurt er als je probeert een element per index toe te wijzen zonder vooraf geheugen voor een nil slice te alloceren?

Er ontstaat een panic index out of range, omdat de slice geen elementen heeft.

var s []int s[0] = 1 // panic: runtime error: index out of range

Typische fouten en anti-patronen

  • Fouten bij het doorgeven van een nil slice of lege slice aan een functie, waar een bepaalde lengte vereist is.
  • Overbelasting van een slice zonder rekening te houden met de groei van de capacity en slecht geschreven loops met append.
  • Pogingen om per index toe te wijzen in plaats van append voor het toevoegen van elementen.

Voorbeeld uit het leven

Negatief geval

Het team besloot in de Go-server overal alleen var s []T te gebruiken, in de veronderstelling dat dit altijd gelijkwaardig is aan make([]T, 0). Als resultaat gaven sommige json-marshals null terug in plaats van [].

Voordelen:

  • Minder geheugenallocaties bij de start.

Nadelen:

  • Onjuiste werking van JSON (als gevolg kwam null in plaats van een array).
  • Runtime fouten bij indextoegang.

Positief geval

Gebruik make([]T, 0, 100) voor preallocatie, en verder alleen append in de loop. Dit minimaliseert geheugenallocaties en resulteert vaak in een prestatieverbetering.

Voordelen:

  • Efficiënt geheugenbeheer.
  • Geen panics en onverwachte waarden bij marshaling.

Nadelen:

  • Mogelijk onterecht geheugenverbruik als het verwachte aantal elementen niet overeenkomt met de opgegeven capacity.