作者 主題: [Golang] 寫入之前如何檢查channel是否可用  (閱讀 3736 次)

0 會員 與 1 訪客 正在閱讀本文。

Yamaka

  • 俺是博士!
  • *****
  • 文章數: 4913
    • 檢視個人資料
    • http://www.ecmagic.com
go 有提供關閉 channel 的函數: close(ch)
在讀取時可以多一個變數取得 channel 的狀態

例如:

代碼: [選擇]
msg, ok := <- ch1
if ok {
  println(msg)
}

這樣可以避免去讀取一個已關閉的 channel
但奇怪的是,go 卻未提供判斷 channel 是否已關閉的功能
例如類似這樣的函數:

isClosed(ch1)

基於常久以來的習慣,總是會想在寫入前先做判斷
一直到目前的 1.5rc1 版,都還沒有這樣的函數
不過還有是其它方式可做到類似效果
只是不用 close(ch)
直接將這個 channel 設為 nil


代碼: [選擇]
package main

import (
  "fmt"
  "math/rand"
  "time"
)

const funcNum, gCountMax int = 20, 360

func main() {
  rand.Seed(time.Now().UTC().UnixNano())
  ch1, ch2 := make(chan string), make(chan string)

  for idx := 0; idx < funcNum; idx++ {
    go func(fid int) {
      fCount := 0
      for {
        if ch1 != nil {
          ch1 <- fmt.Sprintf(" [%v]: %v ", fid, fCount)
          fCount++
          if fCount > 18 {
            ch1 = nil
          }
          time.Sleep(time.Millisecond * time.Duration(rand.Intn(30)*5))
        } else {
          return
        }
      }
    }(idx)
  }

  gCount := 0
  rCount := 0
  go func() {
    defer func() { ch2 <- "Done!" }()
    for {
      select {
      case msg, ok := <-ch1:
        if ok {
          print(msg)
          rCount++
        }
        gCount++
        if gCount >= gCountMax {
          ch1 = nil
        }
      default:
        if ch1 == nil {
          return
        }
      }
    }
  }()
  msg := <-ch2
  fmt.Printf("\n%v, %s\n", rCount, msg)
}


if ch1 != nil {
  ch1 <- fmt.Sprintf(" [%v]: %v ", fid, fCount)
  .....

這邊在寫入 channel 前先判斷是否為 nil
當然,就不要再用 close() 關閉 channel