Go之go与channel组合使用
2024-11-14 04:35:39 203人阅读
1,等待一个事件
1,等待一个事件(Event)
这里的第17行<-ch 将一直阻塞,直到ch被关闭 或者 ch中可以取出值 为止
所以到第17行之后会去执行go后面的func()匿名函数,在里面给ch赋值后(或者close(ch))后,才能继续往后执行
- package main
- import (
- "fmt"
- )
- func main() {
- fmt.Println("Begin doing something!")
- ch := make(chan int)
- go func() {
- fmt.Println("Doing something…")
- ch <- 22
- //close(ch)
- }()
- <-ch //此处将被阻塞,直到ch被关闭 或 有值可以取出
- fmt.Println("Done!")
- }
2,协同多个Goroutines
同上,close channel还可以用于协同多个Goroutines,比如下面这个例子,我们创建了100个Worker Goroutine,这些Goroutine在被创建出来后都阻塞在"<-start"上,直到我们在main goroutine中给出开工的信号:"close(start)",这些goroutines才开始真正的并发运行起来。
- package main
- import "fmt"
- func worker(start chan bool, index int) {
- <-start // 从start中取出数据后,调用20行的case语句
- fmt.Println("This is Worker:", index)
- }
- func main() {
- start := make(chan bool)
- for i := 1; i <= 10; i++ {
- go worker(start, i)
- }
- //给start赋值10次,让worker方法执行10次
- for i := 1; i <= 10; i++ {
- start <- true //给start赋值一次,便执行worker函数一次
- }
- v := 1
- //select 被一直阻塞直到start中数据被取出
- select { //deadlock we expected
- case <-start:
- fmt.Print(v)
- v++
- }
- }
3,Select
- for {
- select {
- case x := <- somechan:
- // … 使用x进行一些操作
- case y, ok := <- someOtherchan:
- // … 使用y进行一些操作,
- // 检查ok值判断someOtherchan是否已经关闭
- case outputChan <- z:
- // … z值被成功发送到Channel上时
- default:
- // … 上面case均无法通信时,执行此分支
- }
- }
下面是一个常见的终结sub worker goroutines的方法,
每个worker goroutine通过select监视一个die channel来及时获取main goroutine的退出通知。
- package main
- import (
- "fmt"
- "time"
- )
- func worker(die chan bool, index int) {
- fmt.Println("Begin: This is Worker:", index)
- for {
- select {
- //case xx:
- //做事的分支
- case <-die: //到这里就被阻塞,运行main中的close后输出 done
- fmt.Println("Done: This is Worker:", index)
- return
- }
- }
- }
- func main() {
- die := make(chan bool)
- for i := 1; i <= 10; i++ {
- go worker(die, i)
- }
- time.Sleep(time.Second * 5)
- close(die)
- select {} //deadlock we expected
- }
有时候终结一个worker后,main goroutine想确认worker routine是否真正退出了,可采用下面这种方法:
- package main
- import (
- "fmt"
- //"time"
- )
- func worker(die chan bool) {
- fmt.Println("Begin: This is Worker")
- for {
- select {
- //case xx:
- //做事的分支
- case <-die: //这里等待27行的赋值语句,如果没有赋值,一直阻塞
- fmt.Println("Done: This is Worker")
- die <- true
- return
- }
- }
- }
- func main() {
- die := make(chan bool)
- go worker(die)
- die <- true
- istrue := <-die //这里等待16行的赋值,赋值完毕后程序继续执行
- fmt.Println("Worker goroutine has been terminated", istrue)
- }
来自为知笔记(Wiz)
Go之go与channel组合使用
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉:
投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。