当前位置: 首页 > 面试题库 >

防止main()函数在Golang中的goroutine完成之前终止

阴永逸
2023-03-14
问题内容

看一下这个人为的例子:

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”。goroutine的输出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恐慌也可以调用
  • 如果要传递WaitGroup给其他函数(而不使用html" target="_blank">全局变量),则必须传递一个指向它的指针,否则WaitGroup将复制(它是一个结构),并且Done()在复制时将不会观察到该方法原本的


 类似资料:
  • 问题内容: 我有以下代码片段。 如您所见,我在goroutine中运行了两个函数errName和errEmail。我将错误类型的通道作为参数传递。如果其中一个先完成,它应该通过通道发送错误并关闭它。因此,第二个仍在运行的goroutine不再需要运行,因为我已经遇到了错误,并且我想终止仍在运行的goroutine。这就是我在上面的示例中尝试达到的目标。 当我运行程序时,出现错误 我知道,当我删除c

  • 我正在学习以下教程:http://mongodb.github.io/mongo-java-driver/3.2/driver-async/reference/crud/。我只是试图连接到数据库,并读取我创建的一个集合,其中包含两个文档: 但我不断得到以下错误:

  • 问题内容: 我需要启动大量goroutine,并等待其终止。直观的方法似乎是使用通道来等待所有操作完成: 但是问题是对象的数量以及goroutine的数量可能会改变。是否可以更改通道的缓冲区大小? 也许有更优雅的方式做到这一点? 问题答案: 我已经使用WaitGroup作为此问题的解决方案。翻译您的当前代码,并附上一些日志,以明确正在发生的事情:

  • 问题内容: 这是我的情况: 在this.handleFormSubmit()上,我正在执行this.setState() 在this.handleFormSubmit()内部,我正在调用this.findRoutes(); -取决于this.setState()的成功完成 this.setState(); 在this.findRoutes被调用之前没有完成… 在调用this.findRoutes(

  • 问题内容: 我正在尝试在Node.js / Express中创建一个路由,该路由从两个查询中读取数据,然后基于来自查询的数据来增加计数。由于Node.js是异步的,因此在读取所有数据之前会显示总计。 我创建了一个简单的示例,以达到我目前正在做的事情 我不确定要等到两个功能都完成后才能打印总计,我该做什么。我是否需要创建一个自定义事件发射器来实现这一目标? 问题答案: 拥抱异步性: 或使用Promi

  • 问题内容: 有什么方法可以防止子类覆盖基类中的方法? 我的猜测是没有,但是我来自.NET界,并且我正试图使我的API尽可能健壮,因此,任何输入都将不胜感激。 可以强制执行吗?我知道编译器无济于事,所以也许通过一些运行时检查来解决?还是这不是一种处理事情的Python方法? 问题答案: 您是对的:您的尝试与Python的结构及其文化背道而驰。 记录您的API,并教育您的用户如何使用它。这是他们的程序