<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## select實現原理 ### case數據結構 源碼包`src/runtime/select.go:scase`定義了表示case語句的數據結構: ~~~go type scase struct { c *hchan // chan kind uint16 elem unsafe.Pointer // data element } ~~~ scase.c為當前case語句所操作的channel指針,這也說明了一個case語句只能操作一個channel。 scase.kind表示該case的類型,分為讀channel、寫channel和default,三種類型分別由常量定義: * caseRecv:case語句中嘗試讀取scase.c中的數據; * caseSend:case語句中嘗試向scase.c中寫入數據; * caseDefault: default語句 scase.elem表示緩沖區地址,根據scase.kind不同,有不同的用途: * scase.kind == caseRecv : scase.elem表示讀出channel的數據存放地址; * scase.kind == caseSend : scase.elem表示將要寫入channel的數據存放地址; ### select實現邏輯 源碼包`src/runtime/select.go:selectgo()`定義了select選擇case的函數: ~~~go func selectgo(cas0 *scase, order0 *uint16, ncases int) (int, bool) ~~~ 函數參數: * cas0為scase數組的首地址,selectgo()就是從這些scase中找出一個返回。 * order0為一個兩倍cas0數組長度的buffer,保存scase隨機序列pollorder和scase中channel地址序列lockorder * pollorder:每次selectgo執行都會把scase序列打亂,以達到隨機檢測case的目的。 * lockorder:所有case語句中channel序列,以達到去重防止對channel加鎖時重復加鎖的目的。 * ncases表示scase數組的長度 函數返回值: 1. int: 選中case的編號,這個case編號跟代碼一致 2. bool: 是否成功從channle中讀取了數據,如果選中的case是從channel中讀數據,則該返回值表示是否讀取成功。 selectgo實現偽代碼如下: ~~~go func selectgo(cas0 *scase, order0 *uint16, ncases int) (int, bool) { //1. 鎖定scase語句中所有的channel //2. 按照隨機順序檢測scase中的channel是否ready // 2.1 如果case可讀,則讀取channel中數據,解鎖所有的channel,然后返回(case index, true) // 2.2 如果case可寫,則將數據寫入channel,解鎖所有的channel,然后返回(case index, false) // 2.3 所有case都未ready,則解鎖所有的channel,然后返回(default index, false) //3. 所有case都未ready,且沒有default語句 // 3.1 將當前協程加入到所有channel的等待隊列 // 3.2 當將協程轉入阻塞,等待被喚醒 //4. 喚醒后返回channel對應的case index // 4.1 如果是讀操作,解鎖所有的channel,然后返回(case index, true) // 4.2 如果是寫操作,解鎖所有的channel,然后返回(case index, false) } ~~~ 特別說明:對于讀channel的case來說,如`case elem, ok := <-chan1:`, 如果channel有可能被其他協程關閉的情況下,一定要檢測讀取是否成功,因為close的channel也有可能返回,此時ok == false。 ***** **【總結】** * select語句中除default外,每個case操作一個channel,要么讀要么寫 * select語句中除default外,各case執行順序是隨機的 * select語句中如果沒有default語句,則會阻塞等待任一case * select語句中讀操作要判斷是否成功讀取,關閉的channel也可以讀取
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看