golang-channel接收数据后,发送一个接收完毕的消息, 以及 sync.WaitGroup 的使用

最下面有个等待组的使用 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()
    
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,753评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,668评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,090评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,010评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,054评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,806评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,484评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,380评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,873评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,021评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,158评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,838评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,499评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,044评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,159评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,449评论 3 374
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,136评论 2 356

推荐阅读更多精彩内容