每日一抄 Go語言使用select切換協程
阿新 • • 發佈:2022-12-12
看了兩篇部落格,一個說:在任何一個 case 中執行 break 或者 return,select 就結束了。
另一個說:break只能跳出select中的一個case
驗證了一下,不知道對不對,感覺是跳出了整個select
func main() { v := make(chan int) o := make(chan bool) select { case d := <-v: fmt.Println("ddd", d) case <-time.After(time.Second * 5): fmt.Println("timeout") //o <- true break } fmt.Println("ssssssssssssss") time.Sleep(time.Second * 100) <-o fmt.Println("程式結束") }
package main import ( "fmt" "time" ) /* 1.監聽的case中,沒有滿足條件的就阻塞 2.多個滿足的條件就任選一個執行 3.select本身不帶迴圈,需要外層的for迴圈 4.default通常不用,會產生忙輪訓 5.break只能跳出select中的一個case 1.加入了預設分支,那麼無論涉及通道操作的表示式是否有阻塞,select語句都不會被阻塞。如果那幾個表示式都阻塞了,或者說都沒有滿足求值的條件,那麼預設分支就會被選中並執行。 2.如果沒有加入預設分支,那麼一旦所有的case表示式都沒有滿足求值條件,那麼select語句就會被阻塞。直到至少有一個case表示式滿足條件為止。 如果select語句發現同時有多個候選分支滿足選擇條件,那麼它就會用一種偽隨機的演算法在這些分支中選擇一個並執行。注意,即使select語句是在被喚醒時發現的這種情況,也會這樣做 */ /* go裡面提供了一個關鍵字select,通過select可以監聽channel上的資料流動 select的用法與switch語言非常類似,由select開始一個新的選擇塊,每個選擇塊條件由case語句來描述 與switch語句可以選擇任何可使用相等比較的條件相比,select有比較多的限制,其中最大的一條限制就是每個case語句裡必須是一個IO操作 for{ select { case <- chan1: // case <- chan2: // default: //case表示式都沒有滿足求值條件, } } */ /* 在一個select語句中,go語言會按順序從頭到尾評估每一個傳送和接收的語句 如果其中的任意一語句可以繼續執行(即沒有被阻塞),那麼就從哪些可以執行的語句中任意選擇一條來使用 如果沒有任意一條語句可以執行(即所有的通道都被阻塞),那麼有兩種可能的情況: 如果給出了default語句,那麼就會執行default語句,同時程式的執行會從select語句後的語句中恢復 如果沒有default語句,那麼select語句將被阻塞,直到至少有一個通訊可以進行下去 */ /* 防止channel超時機制 有時候會出現協程阻塞的情況,那麼我們如何避免這個情況?我們可以使用select來設定超時 */ //func main() { // v := make(chan int) // o := make(chan bool) // // select { // case d := <-v: // fmt.Println("ddd", d) // case <-time.After(time.Second * 5): // fmt.Println("timeout") // //o <- true // break // } // fmt.Println("ssssssssssssss") // // time.Sleep(time.Second * 100) // <-o // // fmt.Println("程式結束") //} //超時這種寫法也常常用來設定定時執行某段函式 //go func() { // select { // case <- time.After(5 * time.Second): // dosomething() // } //} /* default 語句是可選的;fallthrough 行為,和普通的 switch 相似,是不允許的。在任何一個 case 中執行 break 或者 return,select 就結束了。 select 做的就是:選擇處理列出的多個通訊情況中的一個。 如果都阻塞了,會等待直到其中一個可以處理 如果多個可以處理,隨機選擇一個 如果沒有通道操作可以處理並且寫了default 語句,它就會執行:default 永遠是可執行的(這就是準備好了,可以執行)。 在 select 中使用傳送操作並且有 default 可以確保傳送不被阻塞!如果沒有 default,select 就會一直阻塞。 select 語句實現了一種監聽模式,通常用在(無限)迴圈中;在某種情況下,通過 break 語句使迴圈退出。 */ func main() { ch1 := make(chan int) ch2 := make(chan int) go pump1(ch1) go pump2(ch2) go suck(ch1, ch2) time.Sleep(1e9) } func pump1(ch chan int) { for i := 0; ; i++ { ch <- i * 2 } } func pump2(ch chan int) { for i := 0; ; i++ { ch <- i + 5 } } func suck(ch1, ch2 chan int) { for { select { case v := <-ch1: fmt.Printf("Received on channel 1: %d\n", v) case u := <-ch2: fmt.Printf("Received on channel 2: %d\n", u) } } } /* 在程式 goroutine_select.go 中有 2 個通道 ch1 和 ch2,三個協程 pump1()、pump2() 和 suck()。 這是一個典型的生產者消費者模式。 在無限迴圈中,ch1 和 ch2 通過 pump1() 和 pump2() 填充整數; suck() 也是在無限迴圈中輪詢輸入的, 通過 select 語句獲取 ch1 和 ch2 的整數並輸出。 選擇哪一個 case 取決於哪一個通道收到了資訊。程式在 main 執行 1 秒後結束。 ----------------------------------- ©著作權歸作者所有:來自51CTO部落格作者宇宙之一粟的原創作品,請聯絡作者獲取轉載授權,否則將追究法律責任 Go 語言入門很簡單:使用 select 切換協程 https://blog.51cto.com/yuzhou1su/5416579 */