In Go, una struct è una sequenza di elementi con nome chiamati campi, ognuno con un nome e un tipo.
Il nome di un campo deve essere univoco all'interno della struct.
Le struct si possono paragonare alle classi del paradigma della programmazione orientata agli oggetti.
Si crea una nuova struct usando le parole chiave type e struct e si definiscono esplicitamente il nome e il tipo dei campi.
Ad esempio, qui definiamo la struct Shape, che contiene il nome di una forma e la sua dimensione:
type Shape struct {
name string
size int
}
I nomi dei campi nelle struct seguono la convenzione di Go: i campi il cui nome inizia con una lettera minuscola sono visibili solo al codice dello stesso package, mentre quelli il cui nome inizia con una lettera maiuscola sono visibili in altri package.
Una volta definita la struct, devi creare una nuova istanza definendo i campi con il loro nome, in qualsiasi ordine:
s := Shape {
name: "Square",
size: 25,
}
Per leggere o modificare i campi di un'istanza, usa la notazione .:
// Update the name and the size
s.name = "Circle"
s.size = 35
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 35
I campi a cui non viene assegnato un valore iniziale avranno il loro valore zero. Ad esempio:
s := Shape{name: "Circle"}
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 0
Puoi creare un'istanza di una struct senza usare i nomi dei campi, a patto di definirli in ordine:
s := Shape {
"Oval",
20,
}
Tuttavia, questa sintassi è considerata codice fragile, perché può rompersi quando viene aggiunto un campo, soprattutto se il nuovo campo è di un tipo diverso.
Nell'esempio seguente aggiungiamo un campo in più a Shape:
type Shape struct {
name string
description string // new field 'description' added
size int
}
s := Shape{
"Circle",
20,
}
// Since the second field of the struct is now a string and not an int,
// the compiler will throw an error when compiling the program:
// Output: cannot use 20 (type untyped int) as type string in field value
// Output: too few values in Shape{...}
A volte può essere utile avere funzioni che ci aiutano a creare istanze di struct.
Per convenzione, queste funzioni di solito si chiamano New oppure hanno un nome che inizia con New, ma, dato che sono normali funzioni, puoi dare loro il nome che vuoi.
Potrebbero ricordarti i costruttori di altri linguaggi, ma in Go sono solo normali funzioni.
Nell'esempio seguente, una di queste funzioni New viene usata per creare una nuova istanza di Shape e impostare automaticamente un valore predefinito per la size della forma:
func NewShape(name string) Shape {
return Shape{
name: name,
size: 100, //default-value for size is 100
}
}
NewShape("Triangle")
// => Shape { name: "Triangle", size: 100 }
Usare le funzioni New può avere i seguenti vantaggi:
New sono spesso dichiarate nello stesso package delle struct che inizializzano, possono inizializzare anche i campi privati della structPer approfondire questo tipo, puoi consultare queste risorse: Go by Example: Structs, A Tour of Go: Structs o Structures in Go (structs)
new
Un altro modo per creare una nuova istanza di una struct è usare il builtin new:
s := new(Shape) // s will be of type *Shape (pointer to shape)
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: size: 0
In questo esempio, new crea un'istanza della struct Shape con tutti i valori inizializzati al valore zero del loro tipo e restituisce un puntatore a essa.
Nella maggior parte dei casi non vedrai istanze di struct create con il builtin new.
Preferisci sempre usare un letterale di struct, una funzione New personalizzata o qualsiasi altra funzione fornita dal package che ti aiuti a costruire una struct.
Usa il builtin new per creare nuove istanze di struct solo come ultima risorsa.