मॉड्यूल पाठ (3/5)
`चयन करें`: मल्टीप्लेक्सिंग चैनल
select एक ही समय में एकाधिक चैनल संचालन पर प्रतीक्षा करता है।
यह गो संगामिति का 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
}
}सर्वर और कर्मचारियों के लिए विशिष्ट "इवेंट लूप" पैटर्न।
"अक्षम" मामले के रूप में एक शून्य चैनल
एक उन्नत युक्ति: ch == nil के साथ case <-ch कभी नहीं होता है
चयनित. यह आपको किसी मामले को गतिशील रूप से "अक्षम" करने देता है:
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{}= शाश्वत ब्लॉक: लगभग हमेशा एक बग।