Scheda di riferimento per Golang

Comandi e costrutti utili in Go

Indice

Ecco la struttura di base di un programma Go, i pattern per la gestione degli errori e il confronto tra canali e goroutine.

conigli intorno al cartello golang

Foglio di riferimento per Go

Sintassi di base

Dichiarazione del pacchetto

package main

Importazione dei pacchetti

import "fmt"
import (
    "fmt"
    "math"
)

Funzione principale

func main() {
    // Il tuo codice qui
}

Variabili e tipi

Dichiarazione di variabili

var name string
var age int = 25
x := 10 // Dichiarazione breve

Tipi di base

  • bool
  • string
  • int, int8, int16, int32, int64
  • uint, uint8, uint16, uint32, uint64
  • float32, float64
  • complex64, complex128

Strutture di controllo

Istruzione if

if x > 0 {
    // codice
} else if x < 0 {
    // codice
} else {
    // codice
}

Ciclo for

for i := 0; i < 10; i++ {
    // codice
}

Ciclo range

for index, value := range collection {
    // codice
}

Istruzione switch

switch variable {
case value1:
    // codice
case value2:
    // codice
default:
    // codice
}

Funzioni

Dichiarazione di una funzione

func functionName(param1 type1, param2 type2) returnType {
    // codice
    return value
}

Valori di ritorno multipli

func divideAndRemainder(x, y int) (int, int) {
    return x / y, x % y
}

Strutture dati

Array

var numbers int
numbers := int{1, 2, 3, 4, 5}

Slice

slice := []int{1, 2, 3}
slice := make([]int, 3, 5)

Mappe

m := make(map[string]int)
m["key"] = value

Strutture

type Person struct {
    Name string
    Age  int
}
p := Person{Name: "Alice", Age: 30}

Metodi

Dichiarazione di un metodo

func (r Rectangle) Area() float64 {
    return r.width * r.height
}

Interfacce

Dichiarazione di un’interfaccia

type Shape interface {
    Area() float64
}

Concorrenza

Goroutine

go functionName()

Canali

ch := make(chan int)
ch <- value  // Invio
value := <-ch  // Ricezione

Gestione degli errori

Controllo degli errori

if err != nil {
    // Gestisci l'errore
}

Defer

defer file.Close()

Test

Funzione di test

func TestFunction(t *testing.T) {
    // Codice di test
}

Questo foglio di riferimento copre le costruzioni e i comandi più essenziali del linguaggio Go. Include la sintassi di base, le strutture di controllo, le funzioni, le strutture dati, i metodi, le interfacce, i primitivi di concorrenza e la gestione degli errori. Ricorda che Go enfatizza la semplicità e la leggibilità, quindi queste costruzioni formano la base per scrivere codice Go efficiente e chiaro.

Gestione degli errori in Go

La gestione degli errori in Go è semplice e esplicita, enfatizzando chiarezza e robustezza. Ecco le tecniche principali per gestire gli errori in Go:

  1. Restituisci gli errori come valori: Le funzioni che possono fallire dovrebbero restituire un errore come ultimo valore di ritorno. Per esempio:
func Hello(name string) (string, error) {
    if name == "" {
        return "", errors.New("empty name")
    }
    message := fmt.Sprintf("Hi, %v. Welcome!", name)
    return message, nil
}
  1. Controlla sempre gli errori: Dopo aver chiamato una funzione che restituisce un errore, controlla immediatamente se l’errore non è nil. Per esempio:
result, err := SomeFunction()
if err != nil {
    // Gestisci l'errore
    log.Fatal(err)
}
  1. Utilizza l’incapsulamento degli errori: Quando si propagano gli errori lungo la pila di chiamate, incapsulali per aggiungere contesto utilizzando fmt.Errorf() con il verbo %w. Per esempio:
f, err := os.Open(path)
if err != nil {
    return nil, fmt.Errorf("open failed: %w", err)
}
  1. Utilizza defer per la pulizia: Usa defer per assicurarti che le risorse siano correttamente chiuse o pulite, anche se si verifica un errore.

  2. Crea tipi di errore personalizzati: Implementa l’interfaccia error per i tipi di errore personalizzati per fornire informazioni sull’errore più dettagliate.

  3. Utilizza il pacchetto errors: Sfrutta funzioni come errors.New() per creare messaggi di errore semplici, e errors.Is() o errors.As() per il controllo e la conversione dei tipi di errore.

  4. Evita l’uso di panic: Riserva panic per situazioni veramente irrecuperabili. La gestione normale degli errori dovrebbe utilizzare i valori di ritorno.

  5. Fornisci informazioni sull’errore esplicite: Fai in modo che i messaggi sugli errori siano chiari e informativi per aiutare nel debug e nella risoluzione dei problemi.

Seguendo queste pratiche, puoi creare programmi Go robusti che gestiscono gli errori in modo efficace e mantengono la chiarezza del codice.

Migliori pratiche per Goroutine e Canali in Go

Utilizzo efficiente delle Goroutine

  1. Evita la creazione eccessiva di Goroutine: Crea Goroutine con giudizio, considerando la natura del compito e se trae beneficio dall’esecuzione parallela.

  2. Sincronizzazione corretta: Utilizza meccanismi di sincronizzazione come canali o gruppi di attesa per gestire efficacemente le Goroutine e prevenire il consumo di risorse.

  3. Considera la natura del compito: Valuta se un compito trae realmente beneficio dall’esecuzione concorrente prima di utilizzare le Goroutine.

Utilizzo efficace dei Canali

  1. Scegli il tipo di canale appropriato: Utilizza canali non bufferizzati per la sincronizzazione e canali bufferizzati quando devi decoupling le operazioni di invio e ricezione.

  2. Capacità del buffer: Quando si utilizzano canali bufferizzati, considera attentamente la dimensione del buffer per bilanciare prestazioni e utilizzo delle risorse.

  3. Chiudi i canali correttamente: Assicurati che i canali siano chiusi quando non verrà più inviato dati per prevenire blocchi e perdite di risorse.

Pattern di concorrenza

  1. Modello del pool di lavoratori: Implementa pool di lavoratori utilizzando Goroutine e canali per una distribuzione efficiente delle attività e la raccolta dei risultati.

  2. Modello produttore-consumatore: Utilizza Goroutine come produttori e consumatori, con canali che facilitano il flusso di dati tra di essi.

Gestione degli errori e gestione delle risorse

  1. Utilizza defer per la pulizia: Utilizza le istruzioni defer per assicurarti una corretta pulizia delle risorse, anche in presenza di errori.

  2. Gestisci i panici: Implementa recover() in Goroutine di lunga durata per prevenire che l’intero programma venga interrotto a causa di un panico in una singola Goroutine.

Comunicazione e sincronizzazione

  1. Preferisci i canali rispetto alla memoria condivisa: Utilizza i canali per la comunicazione tra Goroutine per evitare condizioni di competizione e semplificare la sincronizzazione.

  2. Utilizza select per più canali: Impiega l’istruzione select per gestire contemporaneamente più operazioni sui canali.

Considerazioni sulle prestazioni

  1. Limita le operazioni concorrenti: Utilizza semafori o pool di lavoratori per limitare il numero di operazioni concorrenti e prevenire l’esaurimento delle risorse.

  2. Evita l’ottimizzazione prematura: Profila il tuo codice per identificare i collo di bottiglia prima di applicare ottimizzazioni concorrenti.

Test e debug

  1. Utilizza il rilevatore di race condition: Esegui regolarmente i test con la bandiera -race per rilevare le race condition.

  2. Scrivi test concorrenti: Crea test che esercitino specificamente i percorsi di codice concorrenti per garantire l’affidabilità.

Seguendo queste buone pratiche, puoi sfruttare efficacemente il modello di concorrenza di Go, rendendo i tuoi programmi più efficienti, mantenibili e meno propensi a problemi comuni legati alla concorrenza.

Vedi altri articoli del blog tecnico.

Aggiornamento di golang su linux

  1. vai e scarica la nuova versione: https://go.dev/doc/install
  2. rimuovi l’antica:
sudo rm -rf /usr/local/go
  1. installa la nuova:
cd Downloads
sudo tar -C /usr/local -xzf go1.24.3.linux-amd64.tar.gz