مرکزی مواد پر جائیں
ماڈیول 7 · سبق 3 از 5کورس میں 33/50~12 min
ماڈیول اسباق (3/5)

منتخب کریں: ملٹی پلیکسنگ چینلز

select ایک ہی وقت میں متعدد چینل آپریشنز پر انتظار کرتا ہے۔ یہ Go concurrency کا switch ہے: یہ آپ کو پہلے پر ردعمل ظاہر کرنے دیتا ہے بہت سے لوگوں کے درمیان چینل تیار ہے۔

نحو

Go
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 ہے: یہ فوری طور پر چلتا ہے جب کوئی کیس تیار نہیں ہوتا ہے (غیر مسدود منتخب کریں)۔

ٹائم آؤٹ پیٹرن

Go
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 کے بعد ایک قدر پیدا کرتا ہے۔ انتظار کو باندھنے کا یہ کلاسک طریقہ ہے۔

ڈیفالٹ کے ساتھ غیر مسدود انتخاب

Go
select {
case msg := <-ch:
    process(msg)
default:
    // niente da fare, prosegui
}

یہ چینل کو بلاک کیے بغیر "پولز" کرتا ہے۔ کوڈ کے راستوں میں مفید ہے۔ لازمی طور پر انتظار کیے بغیر جوابدہ رہنا چاہیے۔

"ڈن چینل" پیٹرن

select کو منسوخی چینل کے ساتھ جوڑیں:

Go
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 کو متحرک کرتا ہے انتظار گوروٹین: مربوط بند۔

منتخب کے ساتھ لوپ

Go
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 کبھی نہیں ہے منتخب یہ آپ کو ایک کیس کو متحرک طور پر "غیر فعال" کرنے دیتا ہے:

Go
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 صرف کو ہینڈل کرتا رہتا ہے۔ دیگر معاملات.

اسے آزمائیں

ورزش#go.m7.l3.e1
کوششیں: 0لوڈ ہو رہا ہے…

ch1 اور ch2 سے موصول ہونے والے دو کیسوں کے ساتھ ایک انتخاب کو نافذ کریں۔ پرنٹ کریں جو پہلے پہنچے۔

ایڈیٹر لوڈ ہو رہا ہے…
اشارہ دکھائیں۔

نحو ` سلیکٹ { کیس ...: ... }` ایک کیس فی چینل کے ساتھ۔

3 کوششوں کے بعد حل دستیاب ہے۔

ورزش#go.m7.l3.e2
کوششیں: 0لوڈ ہو رہا ہے…

time.After(time.Second) کا استعمال کرتے ہوئے سلیکٹ میں ٹائم آؤٹ کیس شامل کریں۔

ایڈیٹر لوڈ ہو رہا ہے…
اشارہ دکھائیں۔

`time.After(d)` ایک چینل ہے جو d کے بعد موصول ہوتا ہے۔

3 کوششوں کے بعد حل دستیاب ہے۔

Quiz#go.m7.l3.e3
تیار

ایک منتخب نان بلاکنگ کیا بناتا ہے؟

Go
select { case v := <-ch: ... ??? }
جواب کے اختیارات

Recap

  • select کئی چینل آپریشنز کے درمیان پہلے تیار کیس کا انتظار کر رہا ہے۔
  • متعدد تیار کیسوں میں چھدم بے ترتیب انتخاب۔
  • default → نان بلاکنگ سلیکٹ (پولنگ)۔
  • time.After(d) ٹائم آؤٹ کے لیے (لوپس میں لیک کو ذہن میں رکھیں: context استعمال کریں)۔
  • پیٹرنز: مکمل چینل، ایونٹ لوپ، کیس کو غیر فعال کرنے کے لیے نیل چینل۔
  • خالی select{} = ابدی بلاک: تقریبا ہمیشہ ایک بگ۔