看一下这个人为的例子:

package main

import "fmt"

func printElo() {
    fmt.Printf("Elo\n")
}

func printHello() {
    fmt.Printf("Hello\n")
}

func main() {
    fmt.Printf("This will print.")
    i := 0
    for i < 10 {
        go printElo()
        go printHello()
        i++
    }
}

该程序的输出将仅为“This will print”。 goroutines printElo()printHello的输出将不会发出,因为,我猜想main()函数线程将在goroutines甚至有机会开始执行之前完成。

使类似的代码在Golang中工作并且不提前终止的惯用方式是什么?

最佳答案

最简单,最干净和“可扩展”的方法是使用 sync.WaitGroup :

var wg = &sync.WaitGroup{}

func printElo() {
    defer wg.Done()
    fmt.Printf("Elo\n")
}

func printHello() {
    defer wg.Done()
    fmt.Printf("Hello\n")
}

func main() {
    fmt.Printf("This will print.")
    i := 0
    for i < 10 {
        wg.Add(1)
        go printElo()
        wg.Add(1)
        go printHello()
        i++
    }
    wg.Wait()
}
输出(在Go Playground上尝试):
This will print.Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
使用sync.WaitGroup时要遵循的简单“规则”:
  • WaitGroup.Add() 语句
  • 之前的“原始” goroutine(开始新的)中调用 go
  • 建议延迟调用 WaitGroup.Done() ,因此即使goroutine panic
  • 也可以调用它
  • 如果您想将WaitGroup传递给其他函数(而不使用包级变量),则必须传递一个指向它的指针,否则将复制WaitGroup(它是一个结构),并且将在副本上调用Done()方法在原始
  • 上不会被观察到

    关于go - 防止main()函数在Golang中的goroutine完成之前终止,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42752705/

    10-12 21:26