Golang中那些未关闭的goroutine都去哪儿了?

Golang中那些未关闭的goroutine都去哪儿了? 我有点好奇Go语言是如何处理那些仍在运行但主goroutine已经终止的goroutine?比如下面的代码片段:

package main

import (
	"fmt"
	"time"
)

func main(){
	message := make(chan string)
	go func(){
		<- message
		time.Sleep(1*time.Second)
		fmt.Println("working...")
	}()
	message <- "hello"
}

我确定goroutine中的打印永远不会执行,因为主goroutine在goroutine中的这些任务完成之前就终止了。Go语言是如何处理这些剩余任务的?

谢谢


更多关于Golang中那些未关闭的goroutine都去哪儿了?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

func main 终止时,整个进程也会随之终止,包括其中的所有 goroutine。

您可以通过使用等待组main 函数等待所有 goroutine 完成。

更多关于Golang中那些未关闭的goroutine都去哪儿了?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,当主goroutine(main函数)终止时,整个程序会立即退出,所有其他正在运行的goroutine都会被强制终止,无论它们处于什么状态。这是Go运行时的一个基本行为特性。

在你的代码示例中,确实如你所说,匿名goroutine中的fmt.Println("working...")永远不会执行。这是因为:

  1. 主goroutine向message通道发送"hello"后立即结束
  2. 程序立即终止,不给匿名goroutine执行time.Sleep和打印的机会

Go运行时不会为这些未完成的goroutine执行任何特殊的清理或资源回收 - 它们只是被强制停止。这可能导致一些问题:

  • 打开的文件描述符可能不会正确关闭
  • 数据库连接可能不会正常释放
  • 内存中的临时数据可能丢失

示例代码演示:

package main

import (
    "fmt"
    "time"
)

func worker(id int) {
    defer fmt.Printf("Worker %d: cleanup completed\n", id)
    fmt.Printf("Worker %d: started\n", id)
    time.Sleep(2 * time.Second)
    fmt.Printf("Worker %d: work completed\n", id)
}

func main() {
    for i := 1; i <= 3; i++ {
        go worker(i)
    }
    
    // 主goroutine立即结束,不给worker goroutines完成的机会
    fmt.Println("Main goroutine finished")
}

输出只会显示:

Main goroutine finished

可以看到,所有的defer语句和后续的打印都不会执行。

正确处理方式示例:

package main

import (
    "fmt"
    "sync"
    "time"
)

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()
    defer fmt.Printf("Worker %d: cleanup completed\n", id)
    fmt.Printf("Worker %d: started\n", id)
    time.Sleep(2 * time.Second)
    fmt.Printf("Worker %d: work completed\n", id)
}

func main() {
    var wg sync.WaitGroup
    
    for i := 1; i <= 3; i++ {
        wg.Add(1)
        go worker(i, &wg)
    }
    
    wg.Wait() // 等待所有worker完成
    fmt.Println("All workers completed, main goroutine finished")
}

这个版本使用sync.WaitGroup确保所有goroutine完成工作后程序才退出。

回到顶部