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