goroutine 并发常见问题实践

程序退出时运行的 goroutine 会不会被终止

测试代码:

import (
    "time"
    "fmt"
)

func main() {
    for i := 0; i < 10; i ++ {
        go func(j int) {
            fmt.Println(j)
        }(i)
    }
    time.Sleep(3*time.Microsecond)
    return
}

运行结果:

➜  test go run ./test_goroutine.go
0
1
2
3
4
5
6
7
8
9
➜  test go run ./test_goroutine.go
5
4
6
➜  test go run ./test_goroutine.go
➜  test go run ./test_goroutine.go

结论:主程序结束时还在运行中的 goroutine 也会终止。

怎样让主程序等待所有 goroutine 退出:

  • 使用管道 channel,适用于单个 goroutine

    func main() {
        ch := make(chan int)
        go func(c chan int){
            time.Sleep(time.Second * 3)
            fmt.Println("goroutine 即将结束。")
            c <- 1
        }(ch)
    
        fmt.Println("主程序即将结束。")
    
        <- ch
    
        fmt.Println("主程序退出。")
    }
    

    运行结果:

    主程序即将结束。
    goroutine 即将结束。
    主程序退出。
    
  • 使用 WaitGroup

    import (
        "fmt"
        "sync"
    )
    
    func main() {
        wg := sync.WaitGroup{}
    
        // wg.Add(10)
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go func(j int, wg *sync.WaitGroup) {
                defer wg.Done()
                fmt.Printf("goroutine %d 即将退出。\n", j + 1)
            }(i, &wg) // 此处注意使用指针传递,否则 goroutine 中的 wg 为新的对象
        }
    
        fmt.Println("主程序即将退出。")
        wg.Wait()
        fmt.Println("主程序退出。")
    }
    

    运行结果:

    主程序即将退出。
    goroutine 4 即将退出。
    goroutine 1 即将退出。
    goroutine 2 即将退出。
    goroutine 3 即将退出。
    goroutine 7 即将退出。
    goroutine 5 即将退出。
    goroutine 6 即将退出。
    goroutine 9 即将退出。
    goroutine 10 即将退出。
    goroutine 8 即将退出。
    主程序退出。
    

你可能感兴趣的:(goroutine 并发常见问题实践)