ProgrammatieGo ontwikkelaar

Wat zijn de bijzonderheden van het werken met strings (string) in Go die je moet weten om onverwachte fouten tijdens het programmeren te voorkomen?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Achtergrond van de vraag: In Go zijn strings (string) een basistype dat vaak wordt gebruikt voor gegevensuitwisseling, logging, parsing, enz. Wat Go onderscheidt, is dat strings immutabel zijn, bestaan uit een onveranderlijke reeks bytes en gegevens in UTF-8 kunnen bevatten.

Probleem: Programmeurs verwarren het werken met strings en byte slices ([]byte), maken fouten bij het wijzigen van een string, bij het splitsen op runen en bij het proberen te werken met multibyte symbolen (bijvoorbeeld Cyrillic, emoji).

Oplossing:

Een string is immutabel; je kunt de elementen niet direct wijzigen — het proberen om s[0] te wijzigen is onterecht. Een string is gecodeerd in UTF-8, wat betekent dat één teken (rune) breder kan zijn dan één byte. Werken met []byte is goedkoper, maar vereist handmatige controle. Het omzetten van string <-> []byte creëert altijd een kopie.

Voorbeeldcode:

s := "hallo" fmt.Println(len(s)) // 12 bytes (Cyrillisch: 2 bytes per letter) fmt.Println(len([]rune(s))) // 6 runen, dat zijn de letters fmt.Println(string([]byte{228, 189, 160, 229, 165, 189})) // Chinese karakters

Belangrijke kenmerken:

  • Een string is immutabel, je kunt niet op index wijzigen.
  • Een string is gecodeerd in UTF-8, niet altijd is 1 teken = 1 byte.
  • Het omzetten van string <-> []byte doet een kopie.

Misleidende vragen.

1. Kun je een enkel karakter van een string wijzigen via index (bijvoorbeeld s[1] = 'a')?

Antwoord: Nee. Strings zijn onveranderlijk, de compiler zal een foutmelding geven. Je moet een nieuwe slice []rune of []byte creëren, deze wijzigen en vervolgens terug converteren naar een string.

2. Waarom komt len(str) niet altijd overeen met het aantal karakters in de string?

Antwoord: len(str) is het aantal bytes en niet runen (symbolen). Voor Cyrillisch of emoji kan een lange string een intuïtief onverwachte waarde geven. Voor het aantal symbolen gebruik []rune:

s := "wereld 😀" fmt.Println(len(s)) // 7 fmt.Println(len([]rune(s))) // 5

3. Wordt een string per referentie of per waarde aan een functie doorgegeven?

Antwoord: Per waarde, maar fysiek wordt er een pointer naar het geheugen en de lengte opgeslagen. Na overdracht 'wijzen' twee variabelen naar dezelfde tekst; een kopie wordt niet automatisch gemaakt. De werkelijke geheugen kopie verschijnt bij het omzetten naar []byte of van []byte naar string.

Typische fouten en anti-patronen

  • Pogingen om een string rechtstreeks te wijzigen via indexering.
  • Vergelijking van de lengte van de string met len — fouten met Unicode.
  • Gebruik van []byte voor serialisatie, maar vergeten dat er encodering is.
  • Vergeten dat string en []byte verschillende objecten in het geheugen zijn.

Voorbeeld uit de praktijk

Negatief geval

Een ontwikkelaar heeft een string met Russische symbolen, neemt de eerste 4 bytes en verwacht de eerste letter te krijgen, maar krijgt slechts de helft van het teken — "gebroken" symbolen.

Voordelen: Het ging snel en kort. Nadelen: Onjuiste behandeling van Unicode-gegevens, "gebroken" strings, paniek bij het proberen om zulke strings op andere plaatsen te parseren.

Positief geval

Strings worden omgezet naar []rune voor het werken met symbolen; na de benodigde handelingen wordt de string weer samengevoegd via string(). Werken met []byte gebeurt alleen voor laag-niveau serialisatie, met inachtneming van de codering.

Voordelen: Correcte behandeling van Unicode, betrouwbaarheid van functies. Nadelen: Iets langzamer, vereist meer geheugen, maar veilig voor alle strings.