<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                有時你可能會發現自己考慮將一個或多個done通道合并到一個done通道中,該通道在任何組件通道關閉時關閉。編寫一個執行這種耦合度較高的select語句是可行的,盡管很冗長;但是有時你無法知道運行狀態下done通道的數量。在這種情況下,或者你如果喜歡單線操作,你可以使用or通道模式將這些通道組合在一起(如果你對done通道看著有點懵,可以先看看上一節)。 這種模式使用遞歸和goroutine創建一個復合done通道。 我們來看一下: ``` var or func(channels ...<-chan interface{}) <-chan interface{} or = func(channels ...<-chan interface{}) <-chan interface{} { //1 switch len(channels) { case 0: //2 return nil case 1: //3 return channels[0] } orDone := make(chan interface{}) go func() { //4 defer close(orDone) switch len(channels) { case 2: //5 select { case <-channels[0]: case <-channels[1]: } default: //6 select { case <-channels[0]: case <-channels[1]: case <-channels[2]: case <-or(append(channels[3:], orDone)...): //6 } } }() return orDone } ``` 1. 這里我們建立了名為or的函數,接收數量可變的通道并返回單個通道。 2. 由于這是個遞歸函數,我們必須設置終止條件。第一個條件是,如果傳入的切片是空的,我們簡單的返回一個nil通道。這與不傳遞通道的想法一致:我們不希望復合通道做任何事。 3. 第二個遞歸終止條件是,如果切片只含有一個元素,我們就返回給元素。 4. 這是該函數最重要的部分,也是遞歸產生的地方。我們建立一個goroutine,以便可以不受阻塞地等待我們通道上的消息。 5. 由于我們這里是遞歸的,每次遞歸調用將至少有兩個通道。作為保持goroutine數量受到限制的優化方法,們在這里為僅使用兩個通道的時設置了一個特殊情況。 6. 在這里,我們遞歸地在第三個索引之后,從我們切片中的所有通道中創建一個or通道,然后從中選擇。遞歸操作會逐層累計直到取到第一個通道元素。我們在其中傳遞了orDone通道,這樣當該樹狀結構頂層的goroutines退出時,結構底層的goroutines也會退出。 這是一種奇妙的做法,你可以將任意數量的通道組合到單個通道中,只要任何作為組件的通道關閉或被寫入,整個通道就會關閉。讓我們來看看該如何進行實際操作。下面這個例子將經過一段時間后關閉通道,然后使用or函數將這些通道合并到一個關閉的通道中: ``` sig := func(after time.Duration) <-chan interface{} { //1 c := make(chan interface{}) go func() { defer close(c) time.Sleep(after) }() return c } start := time.Now() //2 <-or(sig(2*time.Hour), sig(5*time.Minute), sig(1*time.Second), sig(1*time.Hour), sig(1*time.Minute)) fmt.Printf("done after %v", time.Since(start)) //3 ``` 1. 此功能只是創建了一個通道,當后續時間中指定的時間結束時將關閉該通道。 2. 在這里,我們設置追蹤自or函數的通道開始阻塞的起始時間。 3. 在這里我們打印阻塞發生的時間。 這會輸出: ``` done after 1.000216772s ``` 請注意,盡管在我們的調用中放置了多個通道需要多個時間才能關閉,但我們在一秒鐘后關閉的通道會導致由該d調用創建的整個通道關閉。 這是因為它位于樹或函數構建的樹中,它將始終第一個關閉,因此依賴于其關閉的通道也將關閉。 我們以額外創建 f(x)=x/2 個goroutine以"簡潔的"實現該目的,其中x是goroutine的數量。請記住Go的一個優點是能夠快速創建,調度和運行goroutines,并且 該語言積極鼓勵使用goroutines來正確建模問題。無需在前期太擔心在這里創建的分支太多。如果在編譯時你不知道自己正在使用多少個done通道,那么恐怕就沒有其他更好的方法來合并done通道了。 這種模式適用于系統中模塊的交叉點。在這些交叉點,有多種條件通過你的調用堆棧取消goroutines樹。 使用or函數,你可以簡單地將它們組合在一起并將其傳遞給堆棧。 我們將在“context包”中看到另一種更具描述性的做法。 我們也將看到這種模式的變體在第五章“重復請求”中形成更復雜的模式。 * * * * * 學識淺薄,錯誤在所難免。我是長風,歡迎來Golang中國的群(211938256)就本書提出修改意見。
                  <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>

                              哎呀哎呀视频在线观看