ప్రధాన కంటెంట్‌కు వెళ్లండి
మాడ్యూల్ 7 · 5లో పాఠం 3కోర్సులో 33/50~12 min
మాడ్యూల్ పాఠాలు (3/5)

`సెలెక్ట్`: మల్టీప్లెక్సింగ్ ఛానెల్‌లు

select ఒకే సమయంలో బహుళ ఛానెల్ కార్యకలాపాలలో వేచి ఉంది. ఇది 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) d తర్వాత విలువను ఉత్పత్తి చేసే <-chan Timeని అందిస్తుంది. నిరీక్షణను కట్టడి చేయడానికి ఇది క్లాసిక్ మార్గం.

నాన్-బ్లాకింగ్ డిఫాల్ట్‌తో ఎంచుకోండి

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(d)` అనేది d తర్వాత స్వీకరించే ఛానెల్.

3 ప్రయత్నాల తర్వాత పరిష్కారం లభిస్తుంది

Quiz#go.m7.l3.e3
సిద్ధంగా ఉంది

ఎంచుకున్న నాన్-బ్లాకింగ్ ఏమి చేస్తుంది?

Go
select { case v := <-ch: ... ??? }
సమాధాన ఎంపికలు

రీక్యాప్

  • select అనేక ఛానెల్ కార్యకలాపాలలో మొదటి సిద్ధంగా ఉన్న కేసు కోసం వేచి ఉంది.
  • బహుళ సిద్ధంగా ఉన్న కేసులలో సూడో-యాదృచ్ఛిక ఎంపిక.
  • default → నాన్-బ్లాకింగ్ ఎంపిక (పోలింగ్).
  • time.After(d) గడువు ముగిసింది (లూప్‌లలో లీక్‌ని గుర్తుంచుకోండి: contextని ఉపయోగించండి).
  • నమూనాలు: ఒక కేసును నిలిపివేయడానికి ఛానెల్, ఈవెంట్ లూప్, నిల్ ఛానెల్.
  • ఖాళీ select{} = ఎటర్నల్ బ్లాక్: దాదాపు ఎల్లప్పుడూ బగ్.