select語句用於在多個發送/接收信道操作中進行選擇。select語句會一直阻塞,直到發送/接收操作准備就緒。如果有多個信道操作准備完畢,select會隨機地選取其中之一執行。該語法與switch類似,所不同的是,這里的每個case語句都是信道操作。
package main import ( "fmt" "time" ) func server1(ch chan string) { time.Sleep(6 * time.Second) ch <- "from server1" } func server2(ch chan string) { time.Sleep(3 * time.Second) ch <- "from server2" } func main() { output1 := make(chan string) output2 := make(chan string) go server1(output1) go server2(output2) select { case s1 := <-output1: fmt.Println(s1) case s2 := <-output2: fmt.Println(s2) } }
輸出結果:from server2 然后程序終止
假設我們有一個關鍵性應用,需要盡快地把輸出返回給用戶。這個應用的數據庫復制並且存儲在世界各地的服務器上。假設函數server1和server2與這樣不同區域的兩台服務器進行通信。每台服務器的負載和網絡時延決定了它的響應時間。我們向兩台服務器發送請求,並使用select語句等待相應的信道發出響應。select會選擇首先響應的服務器,而忽略其它的響應。使用這種方法,我們可以向多個服務器發送請求,並給用戶返回最快的響應了。
package main import ( "fmt" "time" ) func process(ch chan string) { time.Sleep(10500 * time.Millisecond) ch <- "process successful" } func main() { ch := make(chan string) go process(ch) for { time.Sleep(1000 * time.Millisecond) select { case v := <-ch: fmt.Println("received value: ", v) return default: fmt.Println("no value received") } } }
當select有多個case就緒時,會隨機選擇一個執行
package main import ( "fmt" "time" ) func server1(ch chan string) { ch <- "from server1" } func server2(ch chan string) { ch <- "from server2" } func main() { output1 := make(chan string) output2 := make(chan string) go server1(output1) go server2(output2) time.Sleep(1 * time.Second) select { case s1 := <-output1: fmt.Println(s1) case s2 := <-output2: fmt.Println(s2) } }