select bir goroutine'in birden fazla channel işlemini aynı anda beklemesini sağlar ve hangisi hazırsa onunla ilerler. Kanallar için switch gibidir — eş zamanlı işlemleri koordine etmek, zaman aşımları ve iptal işlemlerini yönetmek için gereklidir.
Temel select — birden fazla kanalı bekleme
select {
case msg1 := <-ch1:
fmt.Println("from ch1:", msg1)
case msg2 := <-ch2:
fmt.Println("from ch2:", msg2)
case ch3 <- "hello": // can also wait to SEND
fmt.Println("sent to ch3")
}
// blocks until ONE case is ready, then runs that case
// if MULTIPLE are ready, one is chosen at RANDOM
select kanallarından biri işleme hazır olana kadar engeller, ardından o durumu çalıştırır. Birden fazla durum aynı anda hazırsa, rasgele birini seçer (açlığa karşı koruma sağlar).
Zaman aşımları — önemli bir kullanım durumu
select {
case result := <-workCh:
fmt.Println("got result:", result)
case <-time.After(2 * time.Second): // fires after 2 seconds
fmt.Println("timed out") // don't wait forever
}
Bir çalışma kanalını time.After ile eşlemek, zaman aşımı eklemek için diyomatik yoldur — sonuç varsa ilerle, aksi takdirde son tarihten sonra pes et. Bu, goroutine'lerin sonsuza kadar engellenmesini önler.
default ile engellemeyen işlemler
select {
case msg := <-ch:
fmt.Println("received:", msg)
default:
fmt.Println("no message ready") // runs immediately if no case is ready
}
// with a default case, select NEVER blocks — it's a non-blocking check
Bir default durumu select 'i engellemez: kanallardan hiçbiri hazır değilse, default beklemek yerine hemen çalışır.
context ile iptal (çok yaygın)
func worker(ctx context.Context, jobs <-chan int) {
for {
select {
case job := <-jobs:
process(job)
case <-ctx.Done(): // context cancelled or timed out
fmt.Println("shutting down:", ctx.Err())
return // clean exit — prevents goroutine leak
}
}
}
case <-ctx.Done() deseni, bir goroutine'nin iş yaparken iptal işlemini dinlemesini sağlar — goroutine'leri durdurmak ve sızıntıları önlemek için standart yoldur.
Yaygın bir desen: select ile döngü
for {
select {
case data := <-dataCh: ...
case <-quit: return
}
}
Neden önemli
select Go eş zamanlılığı için temel bir araçtır — goroutine'lerin birden fazla kanalı koordine etmesi, gerçek eş zamanlı programlar için gerekli olan desenleri etkinleştirmesidir.
Ana kullanımları kritiktir: zaman aşımları (time.After) sonsuza kadar engellemeyi önler; engellemez kanal kontrolleri (default) takılıp kalmaktan kaçınır; ve özellikle iptal (<-ctx.Done()) goroutine'lerin temiz bir şekilde çıkmasını sağlar, bu da goroutine sızıntılarına karşı birincil savunmadır.
select olmadan, birden fazla kanala nazikçe bakamaz, son tarihler belirleyemez veya goroutine'leri kapatma sinyallerine duyarlı hale getiremezsiniz.
select'i anlamak (engelleme-hazır olana kadar davranışı, hazır durumlar arasında rasgele seçim, engellemez için default ve zaman aşımı/iptal deyimleri) robust, sızıntısız eş zamanlı Go yazması için gereklidir ve dildeki temel eş zamanlılık konuları arasındadır.
