最下面有个等待组的使用 sync.WaitGroup
推荐使用等待组!
package main
import "fmt"
/**
channel 例子五:
接收方,接收完毕的时候,通知发送我接收完毕了!
*/
// c 这个chan 表示数据 , dono这个chan是同时是否接收完毕
func donWorker5(id int, c chan int, dono chan bool) {
for n := range c {
fmt.Printf("编号:%d, 接收到数据:%c\n", id, n)
// 往 dono 这个 chan 发送一个值,表示我接收完毕这个数据
dono <- true
// 这里可以单独开一个协程,专门发送,就不会堵塞了
// 后面有更好的办法
// go func() { dono <- true }()
}
}
// 可以创建一个结构,来包装这两个chan
type worker struct {
in chan int
dono chan bool
}
// 创建 chan
func createWorker(id int) worker {
// 创建 chan
w := worker {
in: make(chan int),
dono: make(chan bool),
}
// 调用协程去接收
go donWorker5(id, w.in, w.dono)
return w
}
func chanDemo(){
var workers [10]worker
for i := 0; i< 10 ;i ++ {
workers[i] = createWorker(i)
}
// 发送数据
for i := 0; i < 10 ;i ++ {
workers[i].in <- 'a' + i
// <-workers[i].dono
}
// 发送数据
for i := 0; i < 10 ;i ++ {
workers[i].in <- 'A' + i
// <-workers[i].dono
}
// 接收所有的done消息
for _, worker := range workers {
// 这里接收两遍的原因是上面有两个 for,也就是说每一个 worker都会发送两次
<-worker.dono
<-worker.dono
}
/**
这个时候会出现一个错误:fatal error: all goroutines are asleep - deadlock!
是因为我go语言channel的定义是,既然有了发送方就必须要有接收方!
上面的这个例子是因为我第一组小写的循环开始执行,donWorker5 就开始接收通过channel传输过来的数据,
在接收的时候,又会给发送方发送一个dono的数据,这个时候dono的数据没有地方接收,
只有等到第二组大写循环执行完毕后才能开始接收!
这个时候dono既然没有地方接收,那么就会堵塞掉,因为channel是一个堵塞的队列!
有一个很简单的解决方法,就是 发送 dono的时候,在开启一个协程专门发送dono,
go func(){dono <- true}()
*/
}
func main() {
chanDemo()
}
使用 go 语言提供的方式处理:sync.WaitGroup
package main
import (
"fmt"
"sync"
)
/**
channel 例子六:
接收方,接收完毕的时候,通知发送我接收完毕了!
使用 Go 语言提供的 sync.WaitGroup 的方式,来等待任务结束处理!之前处理方式比较繁琐
// 使用 go 语言提供的等待组,等待组
var wq sync.WaitGroup
// 表示有多少个任务,比如添加20个任务
wq.Add(20)
// 每个任务做完后,在任务做完后调用
wq.Done()
// 等待任务做完,在任务开始后调用
wq.Wait()
*/
// c 这个chan 表示数据
func donWorker6(id int, c chan int, wg *sync.WaitGroup) {
for n := range c {
fmt.Printf("编号:%d, 接收到数据:%c\n", id, n)
// 表示我接收完毕这个数据
wg.Done()
}
}
// 可以创建一个结构
type worker6 struct {
in chan int // chan int 表示我这个chan里面的值只能是 int
wg *sync.WaitGroup
}
// 创建 chan
func createWorker6(id int, wg *sync.WaitGroup) worker6 {
// 创建 chan
w := worker6 {
in: make(chan int), // chan int 表示我这个chan里面的值只能是 int
wg: wg,
}
// 调用协程去接收
go donWorker6(id, w.in, wg)
return w
}
func chanDemo6(){
// 使用 go 语言提供的等待组,等待组
var wg sync.WaitGroup
// 表示有多少个任务,比如添加20个任务
wg.Add(20)
// 每个任务做完后
// wq.Done()
// 等待任务做完
// wq.Wait()
// 创建十个大小的 worker6
var workers [10]worker6
for i := 0; i< 10 ;i ++ {
workers[i] = createWorker6(i, &wg)
}
// 发送数据
for i := 0; i < 10 ;i ++ {
workers[i].in <- 'a' + i
// 也可以每次 加一,就不用写上面的20了
// wg.Add(1)
}
// 发送数据
for i := 0; i < 10 ;i ++ {
workers[i].in <- 'A' + i
// 也可以每次 加一,就不用写上面的20了
// wg.Add(1)
}
// 等待上面两个for循环,也就是20个任务做完
wg.Wait()
/**
这个例子来实现等待任务结束是最好的办法!用 Go 语言提供的方式
*/
}
func main() {
chanDemo6()
}
有疑问加站长微信联系(非本文作者)