• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    go等待一组协程结束的操作方式

    go提供了sync包和channel来解决协程同步和通讯。

    方式1:

    sync.WaitGroup是等待一组协程结束,sync.WaitGroup只有3个方法,Add()添加一个计数,Done()减去一个计数,Wait()阻塞直到所有任务完成。

    package main
    import (
    	"fmt"
    	"sync"
    	"time"
    )
    var wg sync.WaitGroup //定义一个同步等待的组
    func task(i int){
    	fmt.Println("task...",i)
    	//耗时操作任务,网络请求,读取文件
    	time.Sleep(time.Second)
    	wg.Done() //减去一个计数
    }
    func main(){
    	for i:= 0;i10;i++{
    		wg.Add(1) //添加一个计数
    		go task(i)
    	}
    	wg.Wait() //阻塞直到所有任务完成
    	fmt.Println("over")
    }
    

    运行结果:

    task... 9

    task... 4

    task... 6

    task... 0

    task... 7

    task... 5

    task... 1

    task... 2

    task... 8

    task... 3

    over

    方式2:

    利用缓冲信道channel协程之间通讯,其阻塞等待功能实现等待一组协程结束,不能保证其goroutine按照顺序执行

    package main
    import (
     "fmt"
    )
    var ch = make(chan int,10)
    func task(i int){
     fmt.Println("task...",i)
     ch - i
    }
    func main(){
     for i:= 0;i10;i++{
      go task(i)
     }
     for i:= 0;i10;i++{
      - ch
     } 
     fmt.Println("over")
    }
    

    运行结果:

    task... 9

    task... 0

    task... 1

    task... 2

    task... 6

    task... 7

    task... 3

    task... 4

    task... 8

    task... 5

    over

    方式3:

    利用无缓冲的信道channel协程之间通讯,其阻塞等待功能实现等待一组协程结束,保证了其goroutine按照顺序执行

    package main
    import (
     "fmt"
     "time"
    )
    var ch = make(chan int)
    func task(i int){
     fmt.Println("task...",i)
     time.Sleep(time.Second)
      - ch
    }
    func main(){
     for i:= 0;i10;i++{
      go task(i)
      ch - i
     }
     fmt.Println("over")
    }
    

    运行结果:

    task... 0

    task... 1

    task... 2

    task... 3

    task... 4

    task... 5

    task... 6

    task... 7

    task... 8

    task... 9

    over

    补充:Go中使用Channel等待所有协程结束

    让main方法等待所有协程执行完毕再退出。可能一般思路是设置一个共有变量,然后通过修改这个变量的状态。这是通过共享变量来通信的方式,而go要做的是,通过通信来共享内存。

    1. 按顺序执行

    每次通信进行成对通信,当main向协程发送一个写channel时,同时也等待协程返回一个读channel。

    这两个channel一定是成对的,所以构造一个结构体

    type worker struct {
        in chan int
        done chan bool
    }
     
    func chanDemo1(){
        var workers [10]worker 
        for i := 0; i  10; i++ {
            workers[i] = createWorker1(i)
        }
     
        for i := 0; i  10; i++ {
            workers[i].in - 'a' + i
            - workers[i].done
        }
     
        for i := 0; i  10; i++ {
            workers[i].in - 'A' + i
            - workers[i].done
        } 
    }
     
    func createWorker1(id int) worker {
        work := worker{
            in: make(chan int),
            done: make(chan bool),
        }
        go func() {
            for {
                fmt.Printf("Work %d receiverd %c\n", id, - work.in)
                work.done - true
            }
        }()
        return  work
    } 
     
    func main(){
        chanDemo1()
        fmt.Println("over")
    }

    这个执行结果完全是按照0-9,先小写再大写的顺序

    如果这样顺序执行,还要协程干啥

    2. 批量处理

    type worker struct {
        in chan int
        done chan bool
    }
     
    func chanDemo1(){
        var workers [10]worker
        for i := 0; i  10; i++ {
            workers[i] = createWorker1(i)
        }
        for i := 0; i  10; i++ {
            workers[i].in - 'a' + i
        }
        for _, worker  := range workers {
            - worker.done
        }
        for i := 0; i  10; i++ {
            workers[i].in - 'A' + i
        }
        for _, worker  := range workers {
            - worker.done
        }
    }
     
    func createWorker1(id int) worker {
        work := worker{
            in: make(chan int),
            done: make(chan bool),
        }
        go func() {
            for {
                fmt.Printf("Work %d receiverd %c\n", id, - work.in)
                work.done - true
            }
        }()
        return  work
    }

    这样的话,先打印小写,再打印大写,但是大小写时顺序不固定

    3. 完全随机

    func chanDemo1(){
        var workers [10]worker
        for i := 0; i  10; i++ {
            workers[i] = createWorker1(i)
        }
        for i := 0; i  10; i++ {
            workers[i].in - 'a' + i
        }
     
        for i := 0; i  10; i++ {
            workers[i].in - 'A' + i
        }
        for _, worker  := range workers {
            - worker.done
            - worker.done
        }
    }
     
    func createWorker1(id int) worker {
        work := worker{
            in: make(chan int),
            done: make(chan bool),
        }
        go func() {
            for {
                fmt.Printf("Work %d receiverd %c\n", id, - work.in)
     
                // 再开一个协程
                go func() { work.done - true}()
            }
        }()
        return  work
    }

    这种方式就是完全随机了

    使用channel进行树的遍历

    func (node *Node) TraverseFunc(f func(*Node)){
        if node == nil{
            return
        }
        node.Left.TraverseFunc(f)
        f(node)
        node.Right.TraverseFunc(f)
    }
     
    func (node *Node) TraverseWithChannel() chan *Node{
        out := make(chan *Node)
        go func() {
            node.TraverseFunc(func(node *Node) {
                out - node
            })
            close(out)
        }()
        return out
    }
     
    func main(){
        var root Node
        root = Node{Value:3}
        root.Left = Node{}
        root.Right = Node{5,nil,nil}
        root.Right.Left = new(Node)
        root.Left.Right =Node{6,nil,nil}
        root.Traverse()
     
        c:=root.TraverseWithChannel()
        maxNode := 0
        for node := range c{
            if node.Value > maxNode{
                maxNode = node.Value
            }
        }
        fmt.Println("max node value:", maxNode)
     

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

    您可能感兴趣的文章:
    • Go递归修改文件名的实例代码
    • go build 通过文件名后缀实现不同平台的条件编译操作
    • Go并发:使用sync.WaitGroup实现协程同步方式
    • SpringBoot整合MongoDB实现文件上传下载删除
    • golang协程池模拟实现群发邮件功能
    • Go 如何批量修改文件名
    上一篇:golang协程池模拟实现群发邮件功能
    下一篇:Go并发:使用sync.WaitGroup实现协程同步方式
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    go等待一组协程结束的操作方式 等待,一组,协程,结束,的,