網站首頁 編程語言 正文
在golang語言中,select語句 就是用來監聽和channel有關的IO操作,當IO操作發生時,觸發相應的case動作。
有了 select語句,可以實現 main主線程 與 goroutine線程 之間的互動。
1.基本語法
select { case <-ch1 : // 檢測有沒有數據可讀 // 一旦成功讀取到數據,則進行該case處理語句 case ch2 <- 1 : // 檢測有沒有數據可寫 // 一旦成功向ch2寫入數據,則進行該case處理語句 default: // 如果以上都沒有符合條件,那么進入default處理流程 }
注意事項
- select語句 只能用于channel信道的IO操作,每個case都必須是一個信道。
- 如果不設置 default條件,當沒有IO操作發生時,select語句就會一直阻塞;
- 如果有一個或多個IO操作發生時,Go運行時會隨機選擇一個case執行,但此時將無法保證執行順序;
- 對于case語句,如果存在信道值為nil的讀寫操作,則該分支將被忽略,可以理解為相當于從select語句中刪除了這個case;
- 對于空的 select語句,會引起死鎖;
- 對于在 for中的select語句,不能添加 default,否則會引起cpu占用過高的問題;
(1)多個IO操作發生時,case語句是隨機執行的
func main() ?{ ?? ?ch1 := make(chan int, 1) ? // 創建 一個長度帶緩沖的整型通道 ?? ?ch1 <- 1 ? ? ? ? ? ? ? ? ? // 向通道中寫入數據 ?? ?ch2 := make(chan int, 1) ?? ?ch2 <- 2 ?? ?select { ?? ? ? ?case <- ch1: ?? ? ? ??? ?fmt.Println("ch1 read") ?? ??? ?case <- ch2: ?? ??? ??? ?fmt.Println("ch2 read") ?? ?} }
多次執行后,會隨機打印 “ch1 read” 或 “ch2 read”
(2)空select語句
func main() { select { } }
執行后,引發死鎖,打印如下:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [select (no cases)]:
main.main()
? ? ? ? xxx/test.go:4 +0x27
exit status 2
(3)for中的select 引起CPU資源消耗過高
func main() ?{ ?? ?quit := make(chan bool) ?? ?go func() { ?? ??? ?for { ?? ??? ??? ?select { ?? ??? ??? ?case <-quit: ?? ??? ??? ??? ?fmt.Println("quit") ?? ??? ??? ??? ?// 使用 return 就會退出整個goroutine線程;如果使用 break,程序仍然在for循環中執行 ?? ??? ??? ??? ?return ?? ??? ??? ?default: ?? ??? ??? ??? ?fmt.Println("default") ?? ??? ??? ?} ?? ??? ?} ?? ?}() ?? ?time.Sleep(3 * time.Second) ?? ?quit <- true ? ? ? ? ?// 主線程在3秒后,向quit信道寫入數據 ?? ? ?? ?time.Sleep(2 * time.Second) ?? ?fmt.Println("main") }
在for{}的select語句中使用了 default后,線程就會無限執行default條件,直到quit信道中讀到數據,否則會一直在一個死循環中運行,從而導致占滿整個CPU資源。
在 for{}的select語句中,不建議使用 default條件。
2.select語句的實際應用
(1)實現 main主線程與 goroutine線程 之間的交互、通信
// 通過控制臺輸入 "bye", 來控制main函數結束運行 func main() ?{ ?? ?quit := make(chan bool) ?? ?ch := make(chan string) ?? ?go func() { ?? ??? ?for { ?? ??? ??? ?select { ?? ??? ??? ?case name := <-ch: ?? ??? ??? ??? ?fmt.Printf("from main msg: [%v]\n", name) ?? ??? ??? ??? ?if name == "bye" { ?? ??? ??? ??? ??? ?quit <- true ?? ??? ??? ??? ?} else { ?? ??? ??? ??? ??? ?quit <- false ?? ??? ??? ??? ?} ?? ??? ??? ?} ?? ??? ?} ?? ?}() ?? ?for { ?? ??? ?// 控制臺輸入 ?? ??? ?fmt.Print("please input string: ") ?? ??? ?scanner := bufio.NewScanner(os.Stdin) ?? ??? ?scanner.Scan() ?? ??? ?ch <- scanner.Text() ?? ??? ?isOver := <- quit ?? ??? ?if isOver { ?? ??? ??? ?break ?? ??? ?} ?? ?} ?? ?fmt.Println("main over") }
運行:
from main msg: [aaa]
please input string: bbb
from main msg: [bbb]
please input string: bye
from main msg: [bye]
main over
(2)超時實現
func main() ?{ ?? ?quit := make(chan bool) ?? ?ch := make(chan int) ?? ?go func() { ?? ??? ?for { ?? ??? ??? ?select { ?? ??? ??? ?case num := <- ch: ?? ??? ??? ??? ?fmt.Println("num = ", num) ?? ??? ??? ?case <- time.After(5 * time.Second): ?? ??? ??? ??? ?fmt.Println("超時") ?? ??? ??? ??? ?quit <- true ?? ??? ??? ?} ?? ??? ?} ?? ?}() ?? ?for i := 0; i < 2; i++ { ?? ??? ?ch <- i ?? ??? ?time.Sleep(time.Second) ?? ?} ?? ?<- quit ? ? ? ? ? ? ? ? ? // 等待超時后, 結束 main主線程 ?? ?fmt.Println("程序結束") }
原文鏈接:https://blog.csdn.net/grb123/article/details/122907847
相關推薦
- 2022-05-01 C#程序調用cmd.exe執行命令_C#教程
- 2023-03-27 Android進階之從IO到NIO的模型機制演進_Android
- 2023-04-01 Pytorch基礎之torch.randperm的使用_python
- 2022-05-13 深度優先搜索之八皇后問題
- 2022-10-20 VS?Code?常用自定義配置代碼規范保存自動格式化_相關技巧
- 2022-07-17 C++深入講解namespace與string關鍵字的使用_C 語言
- 2022-09-22 Linux 內存和SWAP使用
- 2022-06-01 C語言?柔性數組的使用詳解_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支