go - 防止 main() 函数在 Goroutine 在 Golang 中完成之前终止

标签 go concurrency program-entry-point goroutine

看看这个人为的例子:

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++
    }
}

该程序的输出将只是“这将打印”。 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()go 之前的“原始”goroutine(开始一个新的)中声明
  • 建议调用WaitGroup.Done()延迟,因此即使 goroutine 发生 panic ,它也会被调用
  • 如果您想将 WaitGroup 传递给其他函数(并且不使用包级变量),则必须传递一个指向它的指针,否则 WaitGroup(即a struct) 将被复制,并且在副本上调用的 Done() 方法不会在原始对象上观察到

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

相关文章:

go - 如果自动完成在我的 vs code golang 项目中不起作用,我该怎么办?

mongodb - 为什么 mgo 不能正确解码我的结构?

Java 线程 ID 没有改变

java - Collections.synchronizedList() 使用什么模式

python - 函数中列表的总和

c++ - 在函数中初始化,未在main中初始化

angularjs - go gorilla/sessions angularjs and path, session values not saved (find the bug/place the blame)

go - 存储在 map 中的 Html 模板在第一次调用时崩溃

C信号量奇怪的优先行为

python - python 中 main 中的其他模块无法识别 input()