2016-08-23 46 views
2

雖然有這樣的測試一些代碼:單塊的情況下選擇,將默認:疏導

// ch := make(chan error) 

for { 
    select { 
     case <- ch: 
      println("here") 
    } 
} 

我發現,如果我不添加default的代碼塊:

for { 
    select { 
     case <- ch: 
      println("here") 
     default: 
    } 
} 

如果所需塊,便無法更好就用range,像:

for { 
    for _ = range <- ch { 
     println("here") 
    } 
} 

或者在這種情況下使用select而不是range有什麼區別/優勢?

回答

2

1 - 當你正在處理一個通道,它是確定使用for
考慮這個工作的代碼(The Go Playground):

package main 

import "fmt" 

func main() { 
    ch := make(chan int, 2) 
    ch <- 1 
    ch <- 2 
    close(ch) 
    for range ch { 
    } 
    fmt.Println("Done.") 
} 

這將清空通道。
注意:您應該通過close通道或者您應該使用break語句來完成該循環。


2-當正在處理多個信道可能使用select,像這樣(The Go Playground):

for { 
    select { 
    case <-pause: 
     fmt.Println("pause") 
     select { 
     case <-play: 
      fmt.Println("play") 
     case <-quit: 
      wg.Done() 
      return 
     } 
    case <-quit: 
     wg.Done() 
     return 
    default: 
     work() 
    } 
} 

3-使用零和封閉的通道(The Go Playground):

package main 

import "fmt" 

func main() { 
    var quit chan struct{} // nil 

    select { 
    case <-quit: 
     fmt.Println("1") 
    default: 
     fmt.Println("2") // This runs 
    } 

    quit = make(chan struct{}, 1) 

    select { 
    case <-quit: 
     fmt.Println("10") 
    default: 
     fmt.Println("20") // This runs 
    } 

    quit <- struct{}{} // send 

    select { 
    case <-quit: 
     fmt.Println("100") // This runs 
    default: 
     fmt.Println("200") 
    } 

    close(quit) 

    select { 
    case <-quit: 
     fmt.Println("1000") // This runs 
    default: 
     fmt.Println("2000") 
    } 

    select { 
    case <-quit: 
     fmt.Println("10000") // This runs 
    default: 
     fmt.Println("20000") 
    } 
} 

輸出:

2 
20 
100 
1000 
10000 

Select statements

A 「選擇」 語句選擇其中一組可能的發送或 的接收操作將繼續進行。它看起來類似於「開關」 聲明,但所有情況均涉及通訊 操作。

與RecvStmt的情況可以由RecvExpr的結果分配給一個或 兩個變量,其可以使用一個短可變 聲明聲明。 RecvExpr必須是(可能加括號)接收 操作。最多隻能有一個默認情況,它可能會在案例列表中的任意位置出現 。

執行若干步驟的「select」語句進行的:

對於所有的情況下,在語句,信道操作數接收 操作和信道和右手側的表達式在輸入 「select」語句時,發送 語句按來源順序精確評估一次。結果是一組接收 或從中發送的通道,以及要發送的相應值。無論哪個(如果有的話) 通信操作被選擇繼續進行,將發生該評估中的任何一方的效果。尚未評估具有短變量聲明或 賦值的RecvStmt左邊的 表達式。如果可以繼續進行一個或多個通信,則可以通過統一的僞隨機選擇來選擇可以繼續的單個通信。否則,如果存在默認情況,則選擇 個案。如果沒有默認情況,則「選擇」語句 會阻止,直到至少有一個通訊可以繼續。除非 所選情況是默認情況,否則將執行相應的通訊 操作。如果所選案例是帶有簡短 變量聲明或分配的RecvStmt,則會評估左側表達式 並分配收到的值(或多個值)。執行所選案例的 聲明列表。由於在零通道上的通信 永遠不能進行,只有零通道的選擇和 永遠沒有默認情況下的塊。

1

在你的情況,似乎是一個簡單的循環就足夠了:

for _ = range ch { 
    fmt.Println("drain") 
} 

選擇是必需的,如果你有多個的goroutine處理。巡演有一個range and close的例子。

select的另一種情況是冪等通道關閉:https://play.golang.org/p/_Ol42BvuuS

+3

單例選擇的一種用法是冪等通道關閉:https://play.golang.org/p/_Ol42BvuuS – Kaedys

+0

@Kaedys,感謝這個例子。 – miku

相關問題