ماڈیول اسباق (3/5)
منتخب کریں: ملٹی پلیکسنگ چینلز
select ایک ہی وقت میں متعدد چینل آپریشنز پر انتظار کرتا ہے۔
یہ Go concurrency کا switch ہے: یہ آپ کو پہلے پر ردعمل ظاہر کرنے دیتا ہے
بہت سے لوگوں کے درمیان چینل تیار ہے۔
نحو
select {
case v := <-ch1:
fmt.Println("ch1:", v)
case v := <-ch2:
fmt.Println("ch2:", v)
case ch3 <- 99:
fmt.Println("inviato su ch3")
case <-time.After(time.Second):
fmt.Println("timeout")
default:
fmt.Println("nessuno è pronto")
}سیمنٹکس:
- تمام معاملات کا جائزہ لیا جاتا ہے۔ تیار مقدمات میں سے صرف ایک کا انتخاب کیا گیا ہے۔
- اگر ایک سے زیادہ کیسز تیار ہیں، تو انتخاب سیڈو بے ترتیب ہے (کوئی آرڈر نہیں)۔
- اگر کوئی کیس تیار نہیں ہے:
selectاس وقت تک بلاک کرتا ہے جب تک کہ کوئی تیار نہ ہو جائے۔ - اگر کوئی
defaultہے: یہ فوری طور پر چلتا ہے جب کوئی کیس تیار نہیں ہوتا ہے (غیر مسدود منتخب کریں)۔
ٹائم آؤٹ پیٹرن
select {
case res := <-fetch(url):
use(res)
case <-time.After(2 * time.Second):
log.Println("timeout: fetch troppo lento")
}time.After(d) ایک <-chan Time لوٹاتا ہے جو d کے بعد ایک قدر پیدا کرتا ہے۔
انتظار کو باندھنے کا یہ کلاسک طریقہ ہے۔
ڈیفالٹ کے ساتھ غیر مسدود انتخاب
select {
case msg := <-ch:
process(msg)
default:
// niente da fare, prosegui
}یہ چینل کو بلاک کیے بغیر "پولز" کرتا ہے۔ کوڈ کے راستوں میں مفید ہے۔ لازمی طور پر انتظار کیے بغیر جوابدہ رہنا چاہیے۔
"ڈن چینل" پیٹرن
select کو منسوخی چینل کے ساتھ جوڑیں:
func worker(in <-chan Job, done <-chan struct{}) {
for {
select {
case j := <-in:
process(j)
case <-done:
return // chi gestisce done segnala lo shutdown
}
}
}کوآرڈینیٹر سے close(done) ہر ایک میں case <-done کو متحرک کرتا ہے
انتظار گوروٹین: مربوط بند۔
منتخب کے ساتھ لوپ
for {
select {
case v := <-input:
if v == nil {
return
}
handle(v)
case <-time.After(5 * time.Second):
keepAlive()
case <-ctx.Done():
return
}
}سرورز اور کارکنوں کے لیے عام "ایونٹ لوپ" پیٹرن۔
"غیر فعال" کیس کے طور پر ایک صفر چینل
ایک جدید چال: case <-ch کے ساتھ ch == nil کبھی نہیں ہے
منتخب یہ آپ کو ایک کیس کو متحرک طور پر "غیر فعال" کرنے دیتا ہے:
var in chan int = source()
for {
select {
case v, ok := <-in:
if !ok {
in = nil // disabilita questo case
continue
}
handle(v)
case <-ctx.Done():
return
}
}جب in بند ہوتا ہے، میں اسے کالعدم کرتا ہوں: select صرف کو ہینڈل کرتا رہتا ہے۔
دیگر معاملات.
اسے آزمائیں
ch1 اور ch2 سے موصول ہونے والے دو کیسوں کے ساتھ ایک انتخاب کو نافذ کریں۔ پرنٹ کریں جو پہلے پہنچے۔
اشارہ دکھائیں۔
نحو ` سلیکٹ { کیس ...: ... }` ایک کیس فی چینل کے ساتھ۔
3 کوششوں کے بعد حل دستیاب ہے۔
time.After(time.Second) کا استعمال کرتے ہوئے سلیکٹ میں ٹائم آؤٹ کیس شامل کریں۔
اشارہ دکھائیں۔
`time.After(d)` ایک چینل ہے جو d کے بعد موصول ہوتا ہے۔
3 کوششوں کے بعد حل دستیاب ہے۔
ایک منتخب نان بلاکنگ کیا بناتا ہے؟
select { case v := <-ch: ... ??? }Recap
selectکئی چینل آپریشنز کے درمیان پہلے تیار کیس کا انتظار کر رہا ہے۔- متعدد تیار کیسوں میں چھدم بے ترتیب انتخاب۔
default→ نان بلاکنگ سلیکٹ (پولنگ)۔time.After(d)ٹائم آؤٹ کے لیے (لوپس میں لیک کو ذہن میں رکھیں:contextاستعمال کریں)۔- پیٹرنز: مکمل چینل، ایونٹ لوپ، کیس کو غیر فعال کرنے کے لیے نیل چینل۔
- خالی
select{}= ابدی بلاک: تقریبا ہمیشہ ایک بگ۔