zoukankan      html  css  js  c++  java
  • 【Go】如何终止goroutine

    var wg sync.WaitGroup
    
    func foo(){
    	defer wg.Done()
    	for  {
    		fmt.Println("我是foo函数内的Print")
    		time.Sleep(time.Millisecond*500)
    	}
    }
    
    func main() {
    	wg.Add(1)
    	go foo()
    	wg.Wait()
    }
    

    以上代码永远不会退出,那么如何来通知子goroutine退出呢?

    一、可以添加一个标记值

    // 添加tag标记值
    var wg sync.WaitGroup
    var tag bool // 标记值
    
    func foo(){
        defer wg.Done()
        for  {
            fmt.Println("我是foo函数内的Print")
            time.Sleep(time.Millisecond*500)
            if tag { // tag为真退出foo
                fmt.Printf("foo停止啦")
                break
            }
        }
    }
    
    func tagFunc(tag *bool){
        time.Sleep(time.Second*10)
        *tag = true // 将tag设为真
    }
    
    func main() {
        wg.Add(1)
        go foo()
        go tagFunc(&tag) 
        wg.Wait()
    }

    二、channel传值

    var wg sync.WaitGroup
    var tag  = make(chan bool,1) // 初始化tag channel
    
    func foo(){
        defer wg.Done()
    FOO://for循环标签
        for  {
            fmt.Println("我是foo函数内的Print")
            time.Sleep(time.Millisecond*500)
            select {
            case <- tag:
                fmt.Println("foo停止啦")
          close(tag)
                break FOO // 跳出for虚幻
            default:
            }
        }
    }
    
    func tagFunc(){
        time.Sleep(time.Second*10)
        tag <- true // 向通道传值
        wg.Done()
    }
    
    func main() {
        wg.Add(2)
        go foo()
        go tagFunc()
        wg.Wait()
    }

    三、context(官方推荐)

    // 原理与第二种类似
    var wg sync.WaitGroup
    
    func foo2(ctx context.Context) {
        defer wg.Done()
    FOO2:
        for {
            fmt.Println("我是foo2函数内的Print")
            time.Sleep(time.Millisecond * 500)
            select {
            case <-ctx.Done():// 有值执行退出
                fmt.Println("foo2停止啦")
                break FOO2
            default:// 无值继续循环
            }
        }
    }
    
    
    func foo(ctx context.Context) {
        defer wg.Done()
        wg.Add(1)
        go foo2(ctx) // 将ctx传递给子goroutine
    FOO:
        for {
            fmt.Println("我是foo函数内的Print")
            time.Sleep(time.Millisecond * 500)
            select {
            case <-ctx.Done(): // 有值执行退出
                fmt.Println("foo停止啦")
                break FOO
            default: // 无值继续循环
            }
        }
    }
    
    func tagFunc(cancel context.CancelFunc) {
        time.Sleep(time.Second * 10)
        cancel() //运行cancelFunc
        wg.Done()
    }
    
    func main() {
      // ctx可用于goroutine之间传递,当执行cancelFunc时,ctx.Done()传入空的chan结构体
        ctx, cancelFunc := context.WithCancel(context.Background()) 
        wg.Add(2)
        go foo(ctx)
        go tagFunc(cancelFunc)
        wg.Wait()
    }  
  • 相关阅读:
    matlab从ECG信号数据趋势项的消除
    matlab使用移动平均滤波器、重采样和Hampel过滤器进行信号平滑处理
    R语言如何做马尔科夫转换模型markov switching model
    python主题建模可视化LDA和T-SNE交互式可视化
    R语言Wald检验 vs 似然比检验
    R语言rjags使用随机效应进行臭氧数据分析
    matlab对MCMC贝叶斯方法用于加筋复合板的冲击载荷识别
    4. 纯 CSS 创作一个金属光泽 3D 按钮特效
    3.纯 CSS 创作一个容器厚条纹边框特效
    2.纯 CSS 创作一个矩形旋转 loader 特效
  • 原文地址:https://www.cnblogs.com/cxy2020/p/15795320.html
Copyright © 2011-2022 走看看