Avviare goroutine
La parola chiave go, il ciclo di vita delle goroutine e i WaitGroup
Avviare goroutine è una lezione Go Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Go Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Go Academy include 4 lezioni in totale.
Che cos'è una goroutine?
Una goroutine è una funzione leggera eseguita in concorrenza e gestita dal runtime di Go. Le goroutine sono molto meno costose dei thread del sistema operativo: è possibile eseguirne migliaia:
- Avvio con la parola chiave
go - Stack iniziale di circa 2 KB, che cresce dinamicamente
- Pianificate dal runtime di Go, non dal sistema operativo
- Comunicazione tramite canali, non tramite memoria condivisa
La parola chiave go
Preceda qualsiasi chiamata di funzione con go per avviarla come goroutine:
package main
import ("fmt"; "time")
func greet(name string) {
fmt.Printf("Hello, %s!\n", name)
}
func main() {
go greet("Alice") // runs concurrently
go greet("Bob") // runs concurrently
time.Sleep(100 * time.Millisecond) // wait for goroutines
fmt.Println("done")
}Ciclo di vita di una goroutine
Una goroutine inizia quando viene eseguita l'istruzione go e termina quando la sua funzione restituisce il controllo. Se main termina, tutte le goroutine vengono terminate:
package main
import ("fmt"; "time")
func worker(id int) {
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Duration(id) * 50 * time.Millisecond)
fmt.Printf("Worker %d done\n", id)
}
func main() {
for i := 1; i <= 3; i++ {
go worker(i)
}
time.Sleep(300 * time.Millisecond) // naive wait
}sync.WaitGroup per il coordinamento
Utilizzi sync.WaitGroup invece di sleep per attendere il completamento delle goroutine:
package main
import ("fmt"; "sync")
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // signal completion
fmt.Printf("Worker %d working\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1) // register one goroutine
go worker(i, &wg)
}
wg.Wait() // block until all Done()
fmt.Println("all workers finished")
}Goroutine anonime
Avvii direttamente una funzione anonima come goroutine: è utile per le attività concorrenti definite inline:
package main
import ("fmt"; "sync")
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
i := i // capture loop variable
wg.Add(1)
go func() {
defer wg.Done()
fmt.Printf("goroutine %d\n", i)
}()
}
wg.Wait()
}Problema della cattura della variabile del ciclo
Se non catturate la variabile del ciclo, tutte le goroutine potrebbero vedere lo stesso valore finale: un classico bug di concorrenza in Go:
package main
import ("fmt"; "sync")
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(n int) { // pass i as argument — safe
defer wg.Done()
fmt.Println(n) // prints 0, 1, 2 in some order
}(i)
}
wg.Wait()
}Goroutine e thread
Perché le goroutine sono preferibili ai thread del sistema operativo:
- Stack iniziale di 2 KB contro circa 1 MB per i thread del sistema operativo
- La creazione richiede microsecondi invece di millisecondi
- Il runtime di Go distribuisce le goroutine sui thread del sistema operativo indicati da GOMAXPROCS
- I cambi di contesto tra goroutine sono cooperativi: non coinvolgono il kernel
- Go gestisce la pianificazione, mentre Lei si concentra sulla logica
GOMAXPROCS
runtime.GOMAXPROCS controlla quanti thread del sistema operativo eseguono goroutine in parallelo; per impostazione predefinita corrisponde al numero di CPU:
package main
import ("fmt"; "runtime")
func main() {
// Default: number of available CPU cores
fmt.Println("CPUs:", runtime.NumCPU())
fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0)) // 0 = query without changing
// Set to 1 for debugging race conditions:
// runtime.GOMAXPROCS(1)
fmt.Println("Goroutines:", runtime.NumGoroutine())
}Perdite di goroutine
Si verifica una perdita di goroutine quando una goroutine viene avviata ma non termina mai. Cause comuni: ricezione bloccata su un canale, mutex bloccato o assenza di annullamento:
package main
import ("fmt"; "time"; "runtime")
func leaky() {
ch := make(chan int) // nobody sends to ch
go func() {
v := <-ch // blocks forever — goroutine leaked!
fmt.Println(v)
}()
}
func main() {
leaky()
time.Sleep(10 * time.Millisecond)
fmt.Println("goroutines:", runtime.NumGoroutine()) // > 1
}Buone pratiche per le goroutine
Linee guida per le goroutine:
- Sappia sempre come terminerà una goroutine
- Utilizzi
WaitGroupo i canali per la sincronizzazione, nonsleep - Passi le variabili del ciclo come argomenti di funzione, non tramite una closure
- Annulli le goroutine con il contesto, senza lasciarle in esecuzione
- Utilizzi il race detector:
go run -race main.go
Verifica rapida
Qual è il modo corretto per evitare il bug della cattura della variabile del ciclo nelle goroutine?
Riepilogo: avvio delle goroutine
Riepilogo:
- Avvii con
go fn(): è leggero ed economico - Utilizzi
sync.WaitGroupper attendere:Add(1),defer Done(),Wait() - Catturi le variabili del ciclo tramite un argomento o una nuova dichiarazione
- Sappia sempre come termina ogni goroutine, così da prevenire le perdite
- Utilizzi il flag
-raceper rilevare le race condition sui dati
Domande Frequenti
La lezione «Avviare goroutine» è gratuita?
Sì — il testo completo di «Avviare goroutine» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Go Academy, passa a CoddyKit PRO. Il corso Go Academy include 4 lezioni in totale.
Cosa imparerò in «Avviare goroutine»?
La parola chiave go, il ciclo di vita delle goroutine e i WaitGroup Eserciti Go Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Go Academy?
Non è richiesta alcuna esperienza precedente. Go Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.
Quanto tempo richiede la lezione «Avviare goroutine»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Go Academy?
Sì. Ogni lezione Go Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.