মডিউল পাঠ (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: ... ??? }রিক্যাপ
selectকয়েকটি চ্যানেল অপারেশনের মধ্যে প্রথম প্রস্তুত কেসের জন্য অপেক্ষা করছে৷- একাধিক প্রস্তুত ক্ষেত্রে ছদ্ম-এলোমেলো পছন্দ।
default→ অ-ব্লকিং নির্বাচন (ভোলিং)।time.After(d)টাইমআউটের জন্য (লুপগুলিতে লিক মনে রাখবেন:contextব্যবহার করুন)।- নিদর্শন: সম্পন্ন চ্যানেল, ইভেন্ট লুপ, একটি কেস নিষ্ক্রিয় করতে শূন্য চ্যানেল।
- খালি
select{}= চিরন্তন ব্লক: প্রায় সবসময় একটি বাগ।