Go non converte mai i tipi in modo implicito. Converti tra tipi compatibili con T(v), e tra numeri e testo con il pacchetto strconv. Le due conversioni più cercate:
strconv.Itoa ("integer to ASCII") formatta un int come testo decimale. strconv.Atoi ("ASCII to integer") interpreta un testo come int e restituisce un errore quando il testo non è un numero valido. Controlla sempre quell'errore.
La conversione T(v)
La sintassi di conversione di Go sembra una chiamata di funzione con il nome del tipo di destinazione. Funziona in tre situazioni:
- tra tipi numerici (
int,int64,float64,uint8, ...), - tra
stringe[]byteo[]rune, - tra tipi che condividono lo stesso tipo sottostante (
Celsiusefloat64).
Guarda bene i risultati:
int(3.9)è3eint(-3.9)è-3. La conversione tronca verso lo zero; non arrotonda. Usa primamath.Round,math.Flooromath.Ceilper scegliere il comportamento.math.Roundarrotonda le metà allontanandosi dallo zero, quindi-3.5diventa-4.uint8(300)è44, perché sopravvivono solo gli 8 bit bassi (300 meno 256), eint8(200)è-56per lo stesso motivo. Nessun errore, nessun panic.Celsiusefloat64condividono il tipo sottostante, quindi si convertono liberamente, ma solo in modo esplicito.
I valori stanno in variabili di proposito. Con le costanti, le stesse conversioni non compilano.
Le costanti vengono controllate, le variabili no
Convertire una costante che non ci sta è un errore di compilazione. Convertire una variabile con lo stesso valore fa un wrap-around silenzioso:
fmt.Println(uint8(300)) // compile error
x := 300
fmt.Println(uint8(x)) // 44
./main.go:6:20: constant 300 overflows uint8
Anche convertire una costante non intera in un tipo intero viene rifiutato, mentre lo stesso valore in una variabile viene troncato:
./main.go:7:18: cannot convert -3.9 (untyped float constant) to type int
Se il valore float è fuori dall'intervallo del tipo intero di destinazione (per esempio int64(1e20)), il risultato dipende dall'implementazione: amd64 e arm64, per esempio, danno risposte diverse. Controlla l'intervallo prima di convertire valori non affidabili.
Convertire numeri in stringhe
| Da | Funzione | Esempio | Risultato |
|---|---|---|---|
int | strconv.Itoa(n) | strconv.Itoa(-7) | "-7" |
int64 | strconv.FormatInt(n, base) | strconv.FormatInt(255, 16) | "ff" |
uint64 | strconv.FormatUint(n, base) | strconv.FormatUint(5, 2) | "101" |
float64 | strconv.FormatFloat(f, fmt, prec, 64) | strconv.FormatFloat(3.14159, 'f', 2, 64) | "3.14" |
bool | strconv.FormatBool(b) | strconv.FormatBool(true) | "true" |
| qualsiasi cosa | fmt.Sprint(v) | fmt.Sprint(3.5) | "3.5" |
| qualsiasi cosa, formattata | fmt.Sprintf(format, v) | fmt.Sprintf("%05d", 42) | "00042" |
FormatFloat accetta un byte di formato ('f' per la notazione fissa, 'e' per quella esponenziale, 'g' per la più breve delle due), una precisione (-1 significa "il minor numero di cifre che permette di tornare esattamente al valore") e la dimensione in bit del float originale (64 o 32).
strconv è più veloce di fmt.Sprint, che racchiude il valore in un'interfaccia e passa per il percorso di formattazione generico di fmt. In un ciclo critico la differenza si nota; per conversioni occasionali, scegli quella che si legge meglio.
Convertire stringhe in numeri
| In | Funzione | Restituisce |
|---|---|---|
int | strconv.Atoi(s) | int, error |
| qualsiasi intero con segno | strconv.ParseInt(s, base, bitSize) | int64, error |
| qualsiasi intero senza segno | strconv.ParseUint(s, base, bitSize) | uint64, error |
| float | strconv.ParseFloat(s, bitSize) | float64, error |
| bool | strconv.ParseBool(s) | bool, error |
ParseInt restituisce sempre un int64. L'argomento bitSize (0, 8, 16, 32, 64) stabilisce l'intervallo accettato, quindi il risultato è garantito entrare nel tipo più piccolo quando lo converti. base 0 significa "deduci dal prefisso", quindi 0x1f, 0o17, 0b101 e 1_000 vengono tutti interpretati.
Cosa mostra l'output:
" 42"fallisce.Atoiaccetta un segno facoltativo e delle cifre, nient'altro. L'input letto conbufiodi solito termina con\n, quindi rimuovilo."4.2"non è valido perAtoi. UsaParseFloatper i decimali.- In caso di errore di intervallo,
ParseIntrestituisce il valore più grande che ci sta (127perint8) insieme all'errore. Non usare il valore quando l'errore non è nil. - Gli errori sono valori
*strconv.NumErrorche incapsulanostrconv.ErrSyntaxostrconv.ErrRange, quindierrors.Ispuò distinguerli.
ParseBool accetta 1, t, T, TRUE, true, True e le forme corrispondenti per false. "yes" e "on" sono errori.
La trappola di string(65)
Convertire un intero in string non produce cifre. Produce il carattere con quel code point Unicode:
n := 65
s := string(n) // "A", not "65"
Il compilatore lo accetta, ma go vet lo segnala:
./main.go:10:7: conversion from int to string yields a string of one rune, not a string of digits
Se vuoi davvero il carattere, dillo con una rune: string(rune(n)). Se vuoi il numero come testo, usa strconv.Itoa(n). Convertire una rune o un byte in string va bene ed è comune:
Stringhe, byte e rune
string, []byte e []rune si convertono l'uno nell'altro con T(v). Ogni conversione copia i dati, perché le stringhe sono immutabili e gli slice no:
Converti in []rune quando devi indicizzare o modificare per carattere; converti in []byte per I/O, hashing e modifiche a livello di byte. La pagina su rune e byte tratta UTF-8 in dettaglio.
Conversione e type assertion
Una conversione trasforma un valore da un tipo concreto a un altro. Estrarre il valore concreto da un'interfaccia (any, error, io.Reader) è un'operazione diversa, la type assertion:
var v any = 42
n := v.(int) // type assertion: v holds an int, give it to me
f := float64(n) // conversion: int to float64
// f := float64(v) // compile error: cannot convert v (variable of interface type any)
// // to type float64: need type assertion
Prima asserisci, poi converti. La forma comma-ok n, ok := v.(int) evita un panic quando il tipo è sbagliato.
Riferimento rapido
| Operazione | Codice |
|---|---|
| da int a stringa | strconv.Itoa(n) |
| da int64 a stringa | strconv.FormatInt(n, 10) |
| da stringa a int | n, err := strconv.Atoi(s) |
| da stringa a int64 | n, err := strconv.ParseInt(s, 10, 64) |
| da stringa a float64 | f, err := strconv.ParseFloat(s, 64) |
| da float64 a stringa | strconv.FormatFloat(f, 'f', -1, 64) |
| da float64 a int | int(f) (tronca) oppure int(math.Round(f)) |
| da int a float64 | float64(n) |
| da stringa a []byte | []byte(s) |
| da []byte a stringa | string(b) |
| da rune a stringa | string(r) |
| da bool a stringa | strconv.FormatBool(b) |
| da qualsiasi valore a stringa | fmt.Sprint(v) |
Domande frequenti
Come converto un int in stringa in Go?
Usa strconv.Itoa(n): strconv.Itoa(42) restituisce "42". Per un int64 usa strconv.FormatInt(n, 10). Anche fmt.Sprint(n) funziona con qualsiasi tipo, ma è più lento. Non scrivere string(n): tratta n come un code point Unicode, quindi string(65) è "A".
Come converto una stringa in int in Go?
Usa strconv.Atoi, che restituisce il numero e un errore:
n, err := strconv.Atoi("42")
if err != nil {
// not a valid integer
}
Per una dimensione o una base specifica usa strconv.ParseInt(s, 10, 64), che restituisce un int64. Atoi non rimuove gli spazi, quindi " 42" è un errore; chiama prima strings.TrimSpace.
Come si fa un cast in Go?
Go la chiama conversione, e la sintassi è T(v): float64(n), int(f), []byte(s). Funziona tra tipi numerici, tra stringhe e slice di byte o di rune, e tra tipi con lo stesso tipo sottostante. Non interpreta il testo: trasformare "42" in 42 richiede strconv. Estrarre un tipo concreto da un'interfaccia è una type assertion, v.(T), non una conversione.
Come converto un float in int in Go?
int(f) tronca verso lo zero: int(3.9) è 3 e int(-3.9) è -3. Per arrotondare usa int(math.Round(f)). Se il float è fuori dall'intervallo del tipo intero il risultato dipende dall'implementazione, quindi controlla prima l'intervallo quando il valore arriva da un input.
Perché string(65) restituisce "A" in Go?
Convertire un intero in string lo interpreta come un code point Unicode, e 65 è il code point di A. go vet lo segnala: conversion from int to string yields a string of one rune, not a string of digits. Usa strconv.Itoa(65) per ottenere "65".