即使 main 函数终止,goroutines 也会保持 运行 吗?

Do goroutines keep running even if main function is terminated?

我正在 运行 设置一个服务器,其中 main 触发了几个 go 例程。像这样:

main() {
     go someFn(){
       // will run for infinite time()
     }
     go otherFn()
}

我有两个疑惑:

  1. main函数退出了怎么办?这些线程仍会 运行 还是会随着 main 函数终止?

  2. 如果不是,那么使主要功能 运行 永远/或 运行 直到我需要它的最佳方法是什么?目前,我正在使用 select{} 命令让它永远 运行!有没有比 select{}

    更好更有效的方法

当函数main() returns.

时程序退出

如果 someFnotherFn 之一永远运行,则直接在 main 末尾调用该函数。 main 函数永远不会随着此更改而退出。

如果两个函数都没有永远运行,使用 sync.WaitGroup 等待 goroutines 然后退出。

空的 select 语句 select {} 有效地永远阻塞了一个 goroutine。

[Do] go routines keeps on running even if main function is terminated?

没有

每周询问一次。

我建议完整阅读 the language specification — Go 是极少数语言之一,其语言规范真的可以在两次午餐(或一次午餐 - 如果这是你的,我不知道,第四种编程语言的第三种)。

引用it:

Program execution begins by initializing the main package and then invoking the function main. When that function invocation returns, the program exits. It does not wait for other (non-main) goroutines to complete.


我想补充一点,逻辑上让 main 等待所有非主 goroutines 是一件坏事,原因有两个:

  1. 这很容易造成您可以等待程序关闭一段不确定的时间即使您不希望这样(并且你并不总是想要那个)。

    从逻辑上讲,这需要发明一种“特殊”方式来结束 main — 类似于 abort(3) from C,拥有这种方式肯定会被滥用。

  2. 在实际 需要 等待 goroutines 的任何合理用法都需要显式同步——仅根据语言规范及其 memory model .
    也就是说,当你想等待未完成的 goroutines 时,你必须明确地这样做。

在我看来,当很难记住一个概念时,最好的办法是自己编写这样的概念。

这是一个简单的程序,它演示了 go 例程在 main 函数退出时终止:

package main

import (
    "log"
    "os"
    "time"
)

func main() {
    f, err := os.Create("./test.txt")
    if err != nil {
        log.Fatal("can not write to a file", err)
    }
    go func() {
        for {
            f.WriteString("new line created at: " + time.Now().String() + "\n")
            time.Sleep(1 * time.Second)
        }
    }()
    time.Sleep(5 * time.Second)
    // writing to the file by goroutine will be finished in 5 seconds
    // when main exits
}