分享
  1. 首页
  2. 文章

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

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

向一个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++
 }
}

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

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

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

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏