ProgrammazioneSviluppatore Go

Quali sono le peculiarità del lavoro con le stringhe (string) in Go che è necessario conoscere per evitare errori inaspettati durante la programmazione?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Storia della domanda: In Go, le stringhe (string) sono un tipo di base e frequentemente utilizzato, attivamente impiegato per lo scambio di dati, logging, parsing, ecc. La differenza di Go è che le stringhe sono immutabili, consistono in una sequenza immutabile di byte e possono contenere dati in UTF-8.

Problema: Si confonde il lavoro con le stringhe e i byte slice ([]byte), si commettono errori durante la modifica della stringa, nel taglio tramite run e nel tentativo di lavorare con caratteri multi-byte (ad esempio, cirillico, emoji).

Soluzione:

La stringa è immutabile, non è possibile modificare i suoi elementi direttamente - tentare di cambiare s[0] è improprio. La stringa è codificata in UTF-8, ovvero un simbolo (runa) può essere più ampio di un byte. Lavorare con []byte è più economico, ma richiede un controllo manuale. La conversione string <-> []byte crea sempre una copia.

Esempio di codice:

s := "ciao" fmt.Println(len(s)) // 12 byte (cirillico: 2 byte ciascuno) fmt.Println(len([]rune(s))) // 6 rune, così tante lettere fmt.Println(string([]byte{228, 189, 160, 229, 165, 189})) // ideogrammi cinesi

Peculiarità chiave:

  • La stringa è immutabile, non si può cambiare per indice.
  • La stringa è codificata in UTF-8, non sempre 1 simbolo = 1 byte.
  • La conversione string <-> []byte crea una copia.

Domande insidiose.

1. È possibile cambiare un singolo simbolo della stringa tramite indice (ad esempio, s[1] = 'a')?

Risposta: No. Le stringhe sono immutabili, il compilatore darà un errore. È necessario creare un nuovo slice []rune o []byte, modificarlo, quindi riconvertirlo in stringa.

2. Perché len(str) non corrisponde sempre al numero di simboli nella stringa?

Risposta: len(str) è il numero di byte, non di rune (simboli). Per il cirillico o emoji una stringa lunga può dare un valore inaspettato. Per il numero di simboli utilizza []rune:

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

3. La stringa viene passata per riferimento o per valore in una funzione?

Risposta: Per valore, ma fisicamente all'interno c'è un puntatore alla memoria e la lunghezza. Dopo la trasmissione, due variabili "puntano" allo stesso testo, non viene creata una copia automaticamente. Una copia effettiva della memoria appare durante la conversione in []byte o da []byte a string.

Errori tipici e antipattern

  • Tentativo di modificare la stringa direttamente tramite indicizzazione.
  • Confronto della lunghezza della stringa tramite len - errori con Unicode.
  • Utilizzo di []byte per serializzazione, ma dimenticando la codifica.
  • Dimenticare che string e []byte sono oggetti diversi in memoria.

Esempio dalla vita reale

Caso negativo

Un sviluppatore ha una stringa con simboli russi, prende i primi 4 byte e si aspetta di ottenere la prima lettera, ma appare solo metà simbolo - vengono generati simboli "rotti".

Pro: È stato veloce e breve. Contro: Funzionamento non corretto con i dati Unicode, stringhe "rotte", panic nel tentativo di analizzare tali stringhe in altri luoghi.

Caso positivo

Le stringhe vengono convertite in []rune per lavorare con i simboli, dopo le operazioni richieste, viene di nuovo creata la stringa tramite string(). Il lavoro con []byte viene effettuato solo per la serializzazione a basso livello, tenendo conto della codifica.

Pro: Elaborazione corretta di Unicode, affidabilità delle funzioni. Contro: Un po' più lento, richiede più memoria, ma è sicuro per qualsiasi stringa.