Modül dersleri (1/5)
Goroutinler: hafif paralellik
goroutine, Go tarafından yönetilen bir eşzamanlı yürütme birimidir
çalışma zamanı. Bir işlevin önünde go anahtar sözcüğüyle bir tane başlatırsınız
ara:
go greet("Anna") // chiamata a funzione esistente
go func() { // funzione anonima
fmt.Println("hi")
}()go ifadesi hemen değerini döndürür: goroutine şu şekilde başlar:
paraleldir ve arayan kişi devam eder.
Neden "hafif"
- Başlangıç yığını ~2KB (gerekirse yüzlerce MB'a kadar dinamik olarak büyür).
- Çalışma zamanına göre az sayıda işletim sistemi iş parçacığına çoğullanmıştır (
GOMAXPROCS). - Binlerce/milyonlarca goroutin rutindir; işletim sistemi iş parçacıklarıyla bunlar imkansız olurdu.
Kavramsal olarak bu "eşzamanlı ateşle ve unut" yöntemidir, ancak tüm özellikleriyle birlikte
koordinasyon için deyimsel araçlar (kanallar, sync.WaitGroup,
context).
ana beklemiyor
func main() {
go func() { fmt.Println("ciao dalla goroutine") }()
// main esce subito: niente garanzia che la goroutine completi
}main geri döndüğünde işlem sona erer: goroutinler
"işlerini bitirmek" için basitçe öldürülürler
süreç. Açık senkronizasyon gerekli.
Senkronizasyon: bir önizleme
Sonraki derslerde göreceğiniz üç araç:
// 1) Channel: la goroutine "segnala" via canale
done := make(chan struct{})
go func() {
work()
done <- struct{}{}
}()
<-done // attendi
// 2) sync.WaitGroup: N goroutine
var wg sync.WaitGroup
wg.Add(1)
go func() { defer wg.Done(); work() }()
wg.Wait()
// 3) context: cancellazione/timeout propagati"Klasik" döngü içinde kapatma hatası
Go 1.21'e kadar bu sıkça karşılaşılan bir durumdu:
for i := 0; i < 3; i++ {
go func() { fmt.Println(i) }() // stampa "3 3 3" su versioni vecchie
}Go 1.22'den itibaren her birinde for değişkeni yeni oluşturulmuştur.
yineleme, böylece hata varsayılan olarak düzeltilir. Daha eski kod tabanlarında şunları yapacaksınız:
hala düzeltme modelini görüyorum:
for i := 0; i < 3; i++ {
i := i // shadow esplicito
go func() { fmt.Println(i) }()
}
// oppure passa come argomento:
for i := 0; i < 3; i++ {
go func(n int) { fmt.Println(n) }(i)
}Goroutine != İşletim sistemi iş parçacığı
| Görünüş | Goroutin | işletim sistemi iş parçacığı |
|---|---|---|
| İlk yığın | ~2 KB | 1–8 MB (başlangıçta ayrılır) |
| Yaratılış | nanosaniye | mikrosaniye |
| Planlama | Çalışma zamanına git (kooperatif) | çekirdek (önleyici) |
| Pratik sayım | 100.000+ | birkaç bin |
Tek bir işletim sistemi iş parçacığı birçok goroutine ev sahipliği yapabilir. Çalışma zamanı hareketleri Gerektiğinde iş parçacıkları arasında goroutinler.
Deneyin
Selamlama işlevini bir goroutine olarak başlatın ve zamanla 100 ms bekleyin. Ana programdan çıkmadan önce uyuyun.
İpucu göster
Bir işlev çağrısının önündeki "go" goroutine'i başlatır.
3 denemeden sonra çözüm mevcut
'Merhaba' yazan bir goroutine olarak anonim bir işlev başlatın.
İpucu göster
Anonim bir işlev, sonunda `()`: `go func(){...}()` ile çağrılır.
3 denemeden sonra çözüm mevcut
Bir goroutin tamamlanmadan 'ana' çıkarsa ne olur?
func main() {
go work()
// main ritorna immediatamente
}Özet
go f()aynı anda f()'ı başlatır; hemen geri döner.- Goroutine = ~2 KB başlangıç, birkaç işletim sistemi iş parçacığına çoğullanmış.
mainbeklemez: senkronizasyona ihtiyacınız vardır (kanal/WaitGroup/bağlam).time.Sleepyalnızca öğreticidir, asla üretimde senkronizasyon için değildir.- Go 1.22'den itibaren
fordeğişkeni her yinelemede "taze" olur (artık "3 3 3" hatası yoktur).