Informazioni sui tipi di dati di base
Go è un linguaggio fortemente tipizzato. Ogni variabile dichiarata è associata a un tipo di dati specifico e accetterà solo i valori corrispondenti a tale tipo.
In Go sono disponibili quattro categorie di tipi di dati:
- Tipi di base: numeri, stringhe e valori booleani
- Tipi aggregati: matrici e struct
- Tipi riferimento: puntatori, slice, mappe, funzioni e canali
- Tipi di interfaccia: interfaccia
In questo modulo verranno presentati solo i tipi di base. Non è un problema se non si conoscono gli altri tipi, perché verranno illustrati nei prossimi moduli.
Per iniziare, verranno esaminati i tipi di dati numerici.
Numeri interi
In termini generali, la parola chiave per definire un tipo intero è int
. Tuttavia, Go include anche i tipi int8
, int16
, int32
e int64
, che sono int con una dimensione rispettivamente di 8, 16, 32 o 64 bit. Quando si usa un sistema operativo a 32 bit, se si usa solo int
, la dimensione è in genere di 32 bit. Nei sistemi a 64 bit la dimensione int
è in genere di 64 bit. Questo comportamento può tuttavia differire da un computer a un altro. È possibile usare uint
. Usare questo tipo solo se è necessario rappresentare un valore come numero senza segno per un determinato motivo. Go include anche i tipi uint8
, uint16
, uint32
e uint64
.
Di seguito è riportato un esempio di come usare i vari tipi Integer in Go:
var integer8 int8 = 127
var integer16 int16 = 32767
var integer32 int32 = 2147483647
var integer64 int64 = 9223372036854775807
fmt.Println(integer8, integer16, integer32, integer64)
Nella maggior parte dei casi si userà int
, ma è necessario conoscere gli altri tipi Integer perché in Go int
non è uguale a int32
, anche se la dimensione naturale dei valori Integer è 32 bit. In altre parole, sarà necessario eseguire il cast in modo esplicito quando è necessario un cast. Se si tenta di eseguire un'operazione matematica tra tipi diversi, si otterrà un errore. Si supponga, ad esempio, di avere a disposizione il codice seguente:
var integer16 int16 = 127
var integer32 int32 = 32767
fmt.Println(integer16 + integer32)
Quando si esegue il programma viene generato questo errore:
invalid operation: integer16 + integer32 (mismatched types int16 and int32)
Come si può notare, quando si converte un valore da un tipo a un altro in Go, è necessario indicare in modo esplicito il nuovo tipo. Si vedrà come eseguire correttamente il cast dei tipi alla fine di questo modulo.
Man mano che si procede nell'apprendimento di Go, si potrebbe sentire parlare di rune. rune
è semplicemente un alias per il tipo di dati int32
. Viene usato per rappresentare un carattere Unicode (o un punto di codice Unicode). Ad esempio, si supponga di disporre del codice seguente:
rune := 'G'
fmt.Println(rune)
Quando si esegue il frammento di codice precedente, ci si potrebbe aspettare che il programma stampi G
nel prompt dei comandi. Viene invece visualizzato il numero 71
, che rappresenta il carattere Unicode per G
. Le rune verranno illustrate in maggiore dettagli nei moduli successivi.
È possibile ottenere informazioni sugli intervalli per ogni tipo esaminando il codice sorgente di Go. Conoscere gli intervalli di ogni tipo sarà utile per scegliere il tipo di dati appropriato, evitando così di sprecare i bit in memoria.
Sfida 1
Impostare un'altra variabile di tipo int
e usare il valore dalla variabile integer32
o integer64
per confermare la dimensione naturale della variabile nel sistema. Se si usa un valore superiore a 2.147.483.647 in un sistema a 32 bit, verrà visualizzato un errore di overflow simile al seguente: constant 9223372036854775807 overflows int
.
Soluzione della sfida:
package main import "fmt" func main() { var integer32 int = 2147483648 fmt.Println(integer32) }
Sfida 2
Dichiarare una variabile senza segno come uint
e inizializzarla con un valore negativo come -10
. Quando si tenta di eseguire il programma, viene visualizzato un errore simile al seguente: constant -10 overflows uint
.
Soluzione della sfida:
package main import "fmt" func main() { var integer uint = -10 fmt.Println(integer) }
Numeri a virgola mobile
Go fornisce tipi di dati per due dimensioni dei numeri a virgola mobile: float32
e float64
. È possibile usare questi tipi quando è necessario archiviare numeri grandi e non rientrano in nessuno dei tipi Integer citati in precedenza. La differenza tra questi due tipi è la dimensione massima dei bit che possono contenere. Per capire come usare questi due tipi, vedere le righe seguenti:
var float32 float32 = 2147483647
var float64 float64 = 9223372036854775807
fmt.Println(float32, float64)
È possibile trovare i limiti di questi due tipi usando le costanti math.MaxFloat32
e math.MaxFloat64
, disponibili nel pacchetto math
. Usare il codice seguente per stampare i valori a virgola mobile massimi nel prompt dei comandi:
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(math.MaxFloat32, math.MaxFloat64)
}
I tipi a virgola mobile sono utili anche quando è necessario usare numeri decimali. Ad esempio, è possibile scrivere codice simile al seguente:
const e = 2.71828
const Avogadro = 6.02214129e23
const Planck = 6.62606957e-34
Si noti che con il codice precedente, Go deduce i tipi di dati dai valori usati.
Valori booleani
Un tipo booleano ha solo due valori possibili: true
e false
. Per dichiarare un tipo booleano, si usa la parola chiave bool
. Go è diverso da altri linguaggi di programmazione. In Go non è possibile convertire in modo implicito un tipo booleano in 0 o 1. È necessario farlo in modo esplicito.
È quindi possibile dichiarare una variabile booleana come segue:
var featureFlag bool = true
I tipi di dati booleani verranno usati nel prossimo modulo in cui verranno presentate le istruzioni per i flussi di controllo in Go. Verranno usati anche in moduli successivi.
Stringhe
Verrà infine descritto il tipo di dati più comune in qualsiasi linguaggio di programmazione, ovvero il tipo stringa. In Go la parola chiave string
viene usata per rappresentare un tipo di dati stringa. Per inizializzare una variabile stringa, è necessario definirne il valore racchiuso tra virgolette doppie ("
). Le virgolette singole ('
) vengono usate per singoli caratteri (e per le rune, come si è visto in una sezione precedente).
Il codice seguente, ad esempio, illustra due modi per dichiarare e inizializzare una variabile stringa:
var firstName string = "John"
lastName := "Doe"
fmt.Println(firstName, lastName)
A volte è necessario usare caratteri di escape. A tale scopo, in Go è necessario usare una barra rovesciata (\
) prima del carattere. Ecco gli esempi più comuni di caratteri di escape:
\n
per le nuove righe\r
per i ritorni a capo\t
per le tabulazioni\'
per le virgolette singole\"
per le virgolette doppie\\
per le barre rovesciate
Usare il frammento di codice seguente per testare i caratteri di escape:
fullName := "John Doe \t(alias \"Foo\")\n"
fmt.Println(fullName)
Verrà visualizzato l'output seguente (inclusa la nuova riga):
John Doe (alias "Foo")
Valori predefiniti
Finora, in quasi tutte le dichiarazioni di variabili, queste sono state inizializzate con un valore. Tuttavia, diversamente da altri linguaggi di programmazione, in Go tutti i tipi di dati hanno un valore predefinito quando non si inizializza una variabile. Questa funzionalità è utile perché non è necessario controllare se una variabile è stata inizializzata prima di usarla.
Ecco un elenco di alcuni valori predefiniti per i tipi visti finora:
0
per i tipiint
(e tutti i relativi sottotipi, ad esempioint64
)+0.000000e+000
per i tipifloat32
efloat64
false
per i tipibool
- Un valore vuoto per i tipi
string
Eseguire il frammento di codice seguente per confermare i valori predefiniti elencati in precedenza:
var defaultInt int
var defaultFloat32 float32
var defaultFloat64 float64
var defaultBool bool
var defaultString string
fmt.Println(defaultInt, defaultFloat32, defaultFloat64, defaultBool, defaultString)
È possibile usare codice simile a questo per determinare il valore predefinito per un tipo di dati che non è stato presentato in questa unità.
Conversioni di tipi
In una sezione precedente è stato confermato che il cast implicito non funziona in Go. In Go il cast deve essere eseguito in modo esplicito. Go offre alcuni metodi nativi per la conversione di un tipo di dati in uno diverso. Ad esempio, un modo consiste nell'usare la funzione predefinita per ogni tipo, come indicato di seguito:
var integer16 int16 = 127
var integer32 int32 = 32767
fmt.Println(int32(integer16) + integer32)
Un altro approccio per eseguire il cast in Go prevede l'uso del pacchetto strconv. Ad esempio, per convertire un tipo string
in int
e viceversa, è possibile usare il codice seguente:
package main
import (
"fmt"
"strconv"
)
func main() {
i, _ := strconv.Atoi("-42")
s := strconv.Itoa(-42)
fmt.Println(i, s)
}
Eseguire il codice precedente e verificare che venga eseguito e stampi -42
due volte.
Si noti che è presente un carattere di sottolineatura (_
) usato come nome di una variabile nel codice precedente. In Go _
indica che il valore della variabile non verrà usato e che si vuole ignorarlo. In caso contrario, il programma non verrà compilato perché è necessario usare tutte le variabili dichiarate. Questo argomento verrà ripreso in moduli successivi e si imparerà cosa rappresenta _
.