golang chan詳解

bytemode · · 147 次點擊 · · 開始瀏覽    
## 無緩沖chan 進和出都會阻塞. ## 有緩沖chan 先進先出隊列, 出會一直阻塞到有數據, 進時當隊列未滿不會阻塞, 隊列已滿則阻塞. ## select 1. select 先遍歷所有case, 所有channel表達式都會被求值、所有被發送的表達式都會被求值。求值順序:自上而下、從左到右. 2. 當case沒有阻塞則隨機執行一個沒有阻塞的case就退出select 3. 當所有case阻塞時, 則一直阻塞直到某個case解除阻塞, 但是如果有default則直接執行default 4. 也就是一個select最多只執行一次case里的代碼 5. 要一直檢測case則必須外層使用for循環包起來 ## close(chan) 1. close沒有make的chan會引起panic 2. close以后不能再寫入,寫入會出現panic 3. close之后可以讀取,無緩沖chan讀取返回0值和false,有緩沖chan可以繼續讀取,返回的都是chan中數據和true,直到讀取完所有隊列中的數據,返回默認值和false 4. 重復close會引起panic 5. 只讀chan不能close 6. 不close chan也是可以的,當沒有被引用時系統會自動垃圾回收。 ## 只讀和只寫chan read_only := make (<-chan int) write_only := make (chan<- int) 只讀或者只寫一般用在參數傳遞中。 ## chan和mutex mutex的性能比chan高不少。 比如開源的消息隊列gnatsd(NATS)就很少用chan而使用mutex,其性能是非常高的,比另一個消息隊列nsq高很多。 ## 讀寫Chan 永遠是符號<-進行讀取或者寫入,譬如v,ok := <-c是讀取,而c <- v是寫入。 ```go c := make(chan int, 1) c <- 10 // 寫入chan v := <- c // 從chan中讀取 ``` 下面的例子判斷chan是否關閉: ```go c := make(chan int, 1) c <- 10 v,ok := <- c // 讀取,v=10,ok=true close(c) v,ok := <- c // 讀取,v=0,ok=false ``` 如果寫不進去就丟棄,可以用select: ```go c := make(chan int, 1) select { case c <- 10: // c中放入了10,因為chan的buffer為1 default: } select { case c <- 11: default: // c中只有10,沒有11 } select { case v,ok := <- c: // 讀出來一個,v=10, ok=true default: } select { case v,ok := <- c: default: // 沒有可讀的,走這個分支 } ``` 超時控制 ```go select { case <-timeout: fmt.Println("定時任務") case dd := <-time.After(time.Second * 3): fmt.Println(dd, "任務超時") } ``` ## 判斷closed 讀取時,如果沒有ok,也是可以讀取的。不過如果closed也是能讀的,沒有賦值而已;如果要知道是否closed得加ok,也就是除非chan永遠不關閉,否則讀取應該用v,ok := <-c而不是用v := <-c的方式。 ```go c := make(chan int, 1) c <- 10 close(c) v := <- c // c=10,讀取出來一個 v = <- c // c=0,實際上沒有讀出來,但是判斷不了 c := make(chan int, 1) c <- 10 close(c) v,ok := <- c // c=10,ok=true,讀取出來一個 v,ok = <- c // c=0,ok=false,實際上沒有讀出來 ``` ## For-Range for-range語法可以用到通道上。循環會一直接收channel里面的數據,**直到channel關閉**。不同于array/slice/map上的for-range,channel的for-range只允許有一個變量。 ```go for v:=range aChannel { // use v } ``` 等價于 ```go for { v, ok := <- aChannel if !ok { break } // use v } ``` 注意,for-range對應的channel不能是只寫channel。

入群交流(和以上內容無關):Go中文網 QQ 交流群:729884609 或加微信入微信群:274768166 備注:入群;關注公眾號:Go語言中文網

147 次點擊  ?  1 贊  
加入收藏 微博
暫無回復
添加一條新回復 (您需要 登錄 后才能回復 沒有賬號 ?)
  • 請盡量讓自己的回復能夠對別人有幫助
  • 支持 Markdown 格式, **粗體**、~~刪除線~~、`單行代碼`
  • 支持 @ 本站用戶;支持表情(輸入 : 提示),見 Emoji cheat sheet
  • 圖片支持拖拽、截圖粘貼等方式上傳