首先说一下结论:当父协程是main协程时,父协程退出,父协程下的所有子协程也会跟着退出;当父协程不是main协程时,父协程退出,父协程下的所有子协程并不会跟着退出(子协程直到自己的所有逻辑执行完或者是main协程结束才结束)
再来代码验证一下,下面是代码
package main
import (
"log"
"time"
)
func main(){
defer trace("main")()
go goroutine()
time.Sleep(20*time.Second)
}
func goroutine(){
defer trace("goroutine")()
go goroutinue1()
go goroutinue2()
}
func goroutinue1(){
for i:=0; i<3; i++{
log.Printf("this is goroutine1-%d",i)
time.Sleep(2*time.Second)
}
}
func goroutinue2(){
for i:=0; i<3; i++{
log.Printf("this is goroutine2-%d",i)
time.Sleep(2*time.Second)
}
}
//这个函数可以忽略,其作用只是辅助查看何时进入和退出某个方法
func trace(msg string) func() {
log.Printf("enter %s", msg)
start := time.Now()
return func() { log.Printf("exit %s (%s)", msg, time.Since(start)) }
}
下面是运行结果
2020/11/14 21:47:56 enter main
2020/11/14 21:47:56 enter goroutine
2020/11/14 21:47:56 this is goroutine1-0
2020/11/14 21:47:56 exit goroutine (0s)
2020/11/14 21:47:56 this is goroutine2-0
2020/11/14 21:47:58 this is goroutine1-1
2020/11/14 21:47:58 this is goroutine2-1
2020/11/14 21:48:00 this is goroutine2-2
2020/11/14 21:48:00 this is goroutine1-2
2020/11/14 21:48:16 exit main (20.0115622s)
因此可以验证文章开头的那句结论,因此在项目中也要格外注意父子协程的退出关系,以免造成出现大量的孤儿协程(可以用select结合context优雅的退出协程,具体写法网友已经总结的很全面了,可以去百度一下)