8.8. Channels(管道)

管道可以用于两个goroutines之间的通讯。我们可以用管道传递任意类脂的变量。Go语言中管道是 廉价并且便捷的。 二元操作符 <- 用于向管道发送数据。一元操作符<- 用于从管道接收数据。在函数参数中,管道通过引用传递给函数。

虽然go语言的标准库中提供了互斥的支持,但是我们也可以用一个单一的goroutine提供对变量的 共享操作。 例如,下面的函数用于管理对变量的读写操作。

  type cmd struct { get bool; val int }
  func manager(ch chan cmd) {
          var val int = 0
          for {
                  c := <- ch
                  if c.get { c.val = val ch <- c }
                  else { val = c.val }
          }
  }

在这个例子中,管道被同时用于输入和输出。但是当多个goroutines对变量操作时可能导致 问题:对管道的读操作可能读到的是请求命令。解决的方法是将命令和数据分为不同的管道。

  type cmd2 struct { get bool; val int; ch <- chan int }
  func manager2(ch chan cmd2) {
          var val int = 0
          for {
                  c := <- ch
                  if c.get { c.ch <- val }
                  else { val = c.val }
          }
  }

这里掩饰了如何使用manager2:

  func f4(ch <- chan cmd2) int {
          myCh := make(chan int)
          c := cmd2{ true, 0, myCh }   // Composite literal syntax.
          ch <- c
          return <-myCh
  }