golang中使用一个通道向多个goroutine发送一个数据

· · 1130 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

向一个goroutine通信

向通道发送一次消息只有一个goroutine能收到数据,goroutine向一个通道取数据类似于银行里一个柜台排队取钱,goroutine是那排在长长的队伍,一个通道(channel)就是一个柜台,只有等前一个goroutine取完数据之后,后一个goroutine才能取下一个数据。

  • 一个goroutine循环接收

golang中向一个goroutine只需将值传入通道中,然后在goroutine里从这个通道取值即可,由于只有一个goroutine在循环接收数据,相当于队伍中只有一个人,取完数据之后可以继续站在柜台前等待,例如:

package main

import (
"bufio"
"os"
)

func main() {
  ch, scan:= make(chan string),bufio.NewScanner(os.Stdin)

  // goroutine1
  go func() {
    for {
      fmt.Println(<-ch)
      fmt.Println("goroutine1")
    }
  }()

  // 按一次回车向通道发送一条消息
  for {
  scan.Scan()
  ch <- "Hello goroutine"
  }
}

向通道放入数据时确保有goroutine正在等待着这个通道的数据,若这个通道没有goroutine等待数据则会报错。

fatal error: all goroutines are asleep - deadlock!

  • 多个goroutine循环接收数据

例如这个代码例子,每点一次回车向一个通道发送一次数据,但是一次只能有一个goroutine收到数据。如果接收完数据之后想要再次从这个通道接收数据则需要到队伍的最后重新排队等待。

package main

import (
"bufio"
"fmt"
"os"
)

func main() {
  i, ch, scan := 0, make(chan string), bufio.NewScanner(os.Stdin)
  // goroutine1
  go func() {
    for {
    fmt.Print(<-ch)
    fmt.Println("goroutine1")
  }
}()

// goroutine2
go func() {
  for {
    fmt.Print(<-ch)
    fmt.Println("goroutine2")
  }
}()
  
// goroutine3
  go func() {
    for {
      fmt.Print(<-ch)
      fmt.Println("goroutine3")
    }
  }()

  for {
    scan.Scan()
    ch <- fmt.Sprintf("%d : Hello ", i)
    i++
  }
}

多个goroutine同时接收通道的一条消息

原理很简单,举个例子:假如柜台前所有的人都要看一张通知单,柜员A在柜台前将通知单递给第一个人时,安排柜员B排到队伍的最后;队伍中的第一个人看完通知单后将通知单递回柜台,然后到队伍的最后重新排队(此时排在柜员B的后面),接着下一个人重复第一个人的操作,直到柜员B排到柜台前拿走通知单,走回柜台里(不将通知单给下一个人)。这样第一个看通知单的人重新回到柜台前等待下一个数据。

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
  i, ch, scan := 0, make(chan string), bufio.NewScanner(os.Stdin)
  
  // goroutine1
  go func() {
    for {

      /* 获取通道里的数据 */
      m := <-ch
      fmt.Print(m)
      fmt.Println("goroutine1")

      /* 处理完成之后将数据通过通道递给下一个goroutine
      ch <- m
    }
  }()

  // goroutine2
  go func() {
    for {
      
      /* 此处处理同goroutine1 */
      m := <-ch
      fmt.Print(m)
      fmt.Println("goroutine2")
      ch <- m
    }
  }()

// goroutine3
  go func() {
    for {
      m := <-ch
      fmt.Print(m)
      fmt.Println("goroutine3")
      ch <- m
    }
  }()

  for {
    scan.Scan()
    
    /* 按下一次回车向通道发送一次数据 */
    ch <- fmt.Sprintf("%d : Hello ", i)
    
    /* 向通道里传递数据后立即到队伍后面重新排队 */ 
    <-ch
    i++
  }
}


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:

查看原文:golang中使用一个通道向多个goroutine发送一个数据

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1130 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传