Vai al contenuto
eLearner.app
Modulo 4 · Lezione 4 di 519/50 nel corso~12 min
Lezioni del modulo (4/5)

Stringhe, byte e rune

In Go una string è una sequenza immutabile di byte. Le stringhe letterali sono codificate in UTF-8. Una rune è un alias per int32 e rappresenta un singolo code point Unicode.

Capire la differenza tra byte e rune è essenziale per non incappare in bug quando la stringa contiene accenti, emoji, ideogrammi o qualsiasi carattere non-ASCII.

string = byte, non caratteri

Go
s := "ciaò"
fmt.Println(len(s))   // 5 — non 4!
fmt.Println(s[0])     // 99 ('c' come byte)
fmt.Println(s[3])     // 195 (primo byte di 'ò' in UTF-8)

len(s) ritorna il numero di byte, non di caratteri visibili. L'indicizzazione s[i] ritorna il byte i-esimo (uint8), non il carattere.

for range itera rune

for i, r := range s decodifica UTF-8 al volo: i è il byte-offset dell'inizio del rune, r è il rune (int32):

Go
s := "ciaò"
for i, r := range s {
    fmt.Printf("%d %c (U+%04X)\n", i, r, r)
}
// 0 c (U+0063)
// 1 i (U+0069)
// 2 a (U+0061)
// 3 ò (U+00F2)   <- inizia al byte 3, occupa 2 byte

[]rune(s): indicizzazione per carattere

Conversione esplicita: aloca un nuovo slice di rune. Costoso ma a volte necessario:

Go
runes := []rune("ciaò")
fmt.Println(len(runes))    // 4
fmt.Println(string(runes[3])) // ò

string(runes) è la conversione inversa: prende uno []rune e produce una stringa UTF-8.

Stringhe sono immutabili

Go
s := "ciao"
// s[0] = 'C'   // ERRORE: cannot assign to s[0]

Per modificare, converti in []byte o []rune, opera, riconverti:

Go
b := []byte(s)
b[0] = 'C'
s = string(b)   // "Ciao"

Concatenazione

L'operatore + funziona, ma per molte concatenazioni in loop usa strings.Builder (più efficiente, evita allocazioni intermedie):

Go
var sb strings.Builder
for i := 0; i < 5; i++ {
    sb.WriteString("ab")
}
fmt.Println(sb.String())   // "ababababab"

Pacchetti utili

  • strings: Contains, HasPrefix, Split, Join, ToUpper, Replace...
  • strconv: Atoi, Itoa, ParseFloat, FormatInt...
  • unicode: IsLetter, IsDigit, ToUpper...
  • unicode/utf8: RuneCountInString (alternativa a len([]rune(s))).

Prova tu

Esercizio#go.m4.l4.e1
Tentativi: 0Caricamento…

Itera la stringa s con range e stampa indice e rune con %d %c.

Caricamento editor…
Mostra suggerimento

range su string ritorna byte-offset + rune.

Soluzione disponibile dopo 3 tentativi

Esercizio#go.m4.l4.e2
Tentativi: 0Caricamento…

Converti s in []rune e stampa la sua lunghezza in caratteri.

Caricamento editor…
Mostra suggerimento

Conversione esplicita: `[]rune(s)`.

Soluzione disponibile dopo 3 tentativi

Quiz#go.m4.l4.e3
Pronto

Quanto vale len("ciaò")?

Go
s := "ciaò"
fmt.Println(len(s))
Opzioni di risposta

Recap

  • string = sequenza immutabile di byte, codificata UTF-8.
  • len(s) = byte; s[i] = byte i-esimo (uint8).
  • for i, r := range s decodifica rune; i è il byte-offset.
  • []rune(s) per indicizzare per carattere (costoso, alloca).
  • Per modificare: passa via []byte o []rune.
  • Per concatenare in loop: strings.Builder.
  • Pacchetti chiave: strings, strconv, unicode, unicode/utf8.