Cos'è forme go?

Forme Go

In Go, le forme (o "struct") sono tipi di dati compositi che raggruppano zero o più campi nominati. Sono simili alle classi in altri linguaggi, ma Go non ha il concetto di eredità di classe. Le struct vengono utilizzate per rappresentare entità del mondo reale o concetti che hanno diversi attributi.

Definizione di una struct:

type Persona struct {
    Nome    string
    Cognome string
    Eta     int
}

In questo esempio, Persona è il nome della struct, e Nome, Cognome e Eta sono i campi che la compongono, ognuno con un tipo specifico.

Creazione di istanze di struct:

Esistono diversi modi per creare istanze di struct:

  • Letterale struct:

    p := Persona{Nome: "Mario", Cognome: "Rossi", Eta: 30}
    
  • Ordine dei campi: (Meno consigliato, in quanto sensibile all'ordine e meno leggibile)

    p := Persona{"Mario", "Rossi", 30}
    
  • Utilizzo di new:

    p := new(Persona) // Crea un puntatore a una Persona con valori zero
    p.Nome = "Mario"
    p.Cognome = "Rossi"
    p.Eta = 30
    

Accesso ai campi:

Si accede ai campi di una struct usando l'operatore punto (.).

p := Persona{Nome: "Mario", Cognome: "Rossi", Eta: 30}
fmt.Println(p.Nome) // Stampa "Mario"

Se si ha un puntatore a una struct, si può ancora usare l'operatore punto per accedere ai campi. Go dereferenzia automaticamente il puntatore.

p := new(Persona)
p.Nome = "Mario"
fmt.Println(p.Nome) // Stampa "Mario"

Metodi:

Le struct possono avere metodi associati. Un metodo è una funzione che ha un ricevitore specificato tra la parola chiave func e il nome del metodo. Il ricevitore specifica il tipo su cui il metodo opera.

type Persona struct {
    Nome    string
    Cognome string
    Eta     int
}

func (p Persona) Saluta() string {
    return "Ciao, mi chiamo " + p.Nome + " " + p.Cognome
}

func main() {
    p := Persona{Nome: "Mario", Cognome: "Rossi", Eta: 30}
    fmt.Println(p.Saluta()) // Stampa "Ciao, mi chiamo Mario Rossi"
}

Struct anonime:

Go supporta anche le struct anonime, che sono struct che non hanno un nome di tipo. Sono utili quando si ha bisogno di una struct solo localmente e non si vuole definire un tipo separato.

p := struct {
    Nome    string
    Cognome string
}{
    Nome: "Mario",
    Cognome: "Rossi",
}

fmt.Println(p.Nome) // Stampa "Mario"

Campi embedded:

Go consente l'embedding di struct all'interno di altre struct. Questo permette di riutilizzare i campi e i metodi di una struct esistente all'interno di una nuova struct.

type Indirizzo struct {
    Via      string
    Citta    string
    CAP     string
}

type Persona struct {
    Nome     string
    Cognome  string
    Eta      int
    Indirizzo Indirizzo // Indirizzo è embedded in Persona
}

func main() {
    p := Persona{
        Nome:    "Mario",
        Cognome: "Rossi",
        Eta:     30,
        Indirizzo: Indirizzo{
            Via:   "Via Roma, 1",
            Citta: "Roma",
            CAP:   "00100",
        },
    }

    fmt.Println(p.Indirizzo.Citta) // Stampa "Roma"
}

Si può anche avere un campo embedded anonimo:

type Indirizzo struct {
    Via      string
    Citta    string
    CAP     string
}

type Persona struct {
    Nome     string
    Cognome  string
    Eta      int
    Indirizzo // Indirizzo è embedded anonimamente in Persona
}

func main() {
    p := Persona{
        Nome:    "Mario",
        Cognome: "Rossi",
        Eta:     30,
        Indirizzo: Indirizzo{
            Via:   "Via Roma, 1",
            Citta: "Roma",
            CAP:   "00100",
        },
    }

    fmt.Println(p.Citta) // Stampa "Roma" (accesso diretto)
}

L'accesso diretto ai campi embedded anonimi è possibile perché Go "promuove" i campi della struct embedded nella struct esterna.

Considerazioni importanti:

  • Le struct sono tipi valore. Quando una struct viene assegnata a una nuova variabile o passata come argomento a una funzione, viene creata una copia della struct. Per evitare questo, si possono usare i puntatori alle struct.
  • I campi di una struct possono essere di qualsiasi tipo, inclusi altri tipi struct, array, slice, map e interfacce.
  • Le struct possono implementare interfacce definendo metodi che corrispondono alla signature dell'interfaccia.
  • Le struct sono fondamentali per la gestione dei dati in Go e sono ampiamente utilizzate per rappresentare oggetti complessi e strutture di dati.
  • Comprendere i tipi di dato in Go è fondamentale per lavorare con le struct in modo efficace.

Spero che queste informazioni siano utili!