新手问题 golang如何结束goroutine

spider · 2017年07月26日 · 最后由 plain 回复于 2017年07月26日 · 283 次阅读

下面的代码开启了10个消费者,消费者接收某消息停止所有 goroutine 怎么实现?

package main

import (

    "sync"
    "fmt"
    "strconv"
    "time"
    //"runtime"
)

var wait sync.WaitGroup

var input = make(chan string)


func inputConsumer() {


    for in := range input {


        fmt.Println(in)

        if in=="5" {

            //这里结束所有goroutines

        }
        //println(runtime.NumGoroutine(),"===")

        time.Sleep(time.Second)

        wait.Done()
    }
}

var inputGroup sync.WaitGroup

func main() {

    //控制goroutine数量为10个
    for i := 0; i <10; i++ {
        go inputConsumer()
    }

    inputGroup.Add(1)

    go func(){
        for j:=1 ;j<20;j++ {
            wait.Add(1)
            input <- strconv.Itoa(j)
        }

        inputGroup.Done()

    }()

    inputGroup.Wait()

    wait.Wait()

}

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio

golang 有个包叫 context,完美解决方案 如果不想用标准包,看看这个包tomb, golang 1.6 之前的解决方案

其实还有一种较搓的方案,在生产者的 goroutine 中将消费的 channel close 掉,消费者每次监听该 channel 的时候判断是否已经 close 了,如果是,那么就 return

@xkey,这代码死锁

package main

import (
    "context"
    "log"
    "os"
    //"time"
    "sync"
    "fmt"
)

var logg *log.Logger
var ctx, cancel = context.WithCancel(context.Background())
var jobs = make(chan int)
var inputGroup sync.WaitGroup
var all sync.WaitGroup


func doStuff(ctx context.Context) {


    for {
        //time.Sleep(1 * time.Second)
        select {
        case <-ctx.Done():
            logg.Printf("done")
            return
        case proc := <-jobs:
            fmt.Println(proc)
            all.Done()
            if (proc==20){

                cancel()
            }
        default:

        }
    }

}

func main() {
    logg = log.New(os.Stdout, "", log.Ltime)

    go doStuff(ctx)

    inputGroup.Add(1)



    go func(){

        for i := 0; i < 100; i++ {
            all.Add(1)
            jobs <- i
        }
        inputGroup.Done()


    }()


    inputGroup.Wait()
    all.Wait()

    logg.Printf("down")
}

close 一个 channal,所有监听的都接收到。

select {
    case <- some work chan:
    case <- will close chan:   //close这个chan
        fmt.Println('receive close')
}
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册