关于Go语言的非main函数退出后,其子协程是否会退出这件事

关于Go语言的非main函数退出后,其子协程的是否退出这件事

你知道的

我们都知道,如果在mian中启动一个协程,如果main结束的时候,这个协程还有结束的话,系统也会强制关闭这个协程
最简单的例子如下:

func main() {
	go func() {
		time.Sleep(time.Second)
		fmt.Println("THIS IS KID")
	}()

	fmt.Println("THIS IS MAIN")
}

输出:
THIS IS MAIN

但是,你在编程的时候,有没有想过:
假如你有一个非main的函数,里面也启动了一个协程,如果这个非main结束的话,里面的那个子协程会结束吗?
你可以先自己想一下,先别看下面的内容,欢迎留言!!!

实验验证

再看之前,先想明白问题是什么?
那么我们来实验验证一下,不就得了。
直接上最简单的代码:

func test() int {
	go func() { //子协程
		time.Sleep(time.Second*2)
		fmt.Println("非main函数的子协程结束")
	}()
	fmt.Println("非main函数结束")
	return 1
}
func main() {
	fmt.Println("非main函数返回值为", test())
	time.Sleep(time.Second*5)
	fmt.Println("main函数结束")
}

输出:
非main函数结束
非main函数返回值为 1
非main函数的子协程结束
main函数结束

由于test中的子协程延迟了2s,所以test函数会先结束,故打印出了“非main函数结束”和“非main函数返回值为 1”,因为我们在main中加了5s的延迟(为了避免main退出带来的影响),故肯定不会早于test子协程退出。这个时候打印出了“非main函数的子协程结束”,说明test的子协程并没有因为test的结束而结束,在之后,打印出“main函数结束”,main函数结束

由此,我们可以的得出结论:
非main函数退出后,其子协程是不会退出的

白话:A不是main程的情况下,在A程里开启B程,A程执行完,A程return之后,B程不受影响,不会挂掉。

所有的协程都是同一级别的,别管在哪个地方启动的协程(当然,主main退出的话,全部的协程也就退出了)

我们再来看一个例子:结合上通道

直接上代码

func main() {
	fmt.Println("非main函数返回值为", mirroredQuery())
	time.Sleep(time.Second*5)
	fmt.Println("main函数结束")
}

func mirroredQuery() string {
	responses := make(chan string)
	go func() { responses <- request("A",3)
				fmt.Println("A协程结束")
	}()

	go func() { responses <- request("B",1)
				fmt.Println("B协程结束")
	}()
	return <-responses
}

func request(hostname string,n int) (response string) {
	time.Sleep(time.Second*time.Duration(n))
	return hostname
}

输出:
B协程结束
非main函数返回值为 B
main函数结束

看到这里,你是不是又有疑问了?上边他娘的不是刚证明了吗,怎么这里又不好使了呢?
这里呢,都是因为这个responses := make(chan string)搞的鬼
我们可以看到,它是一个无缓冲通道,什么意思,也就是说,之后这个通道在接收的时候,我们才能写入,或者说,之后我们写入了的时候,它必须在等着接收,不能像有缓冲通道那样,我放上就行了,然后,你有空了,你就来取。

这样的话,”B协程结束“和”非main函数返回值为 B“先输出
注意,此时我们的A协程是没有死的,因为main又没结束。而是卡在了responses <- request(“A”,3),就是因为通道是无缓冲的,且mirroredQuery函数已经结束了,不会再去执行<-responses这个读的操作, 所以A协程就一直阻塞在responses <- 这个地方,永远动不了了
这就造成了goroutines泄露的问题,是Go语言新手经常遇到的问题,与垃圾回收不同,泄露的goroutines并不会被自动回收。

在这里,可以改为带缓冲的通道,使得数据能写入到chan,保证协程可以结束

responses := make(chan string,3)

输出:
B协程结束
非main函数返回值为 B
A协程结束
main函数结束

参考链接

关于go在函数退出后子协程的退出问题

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋山刀名鱼丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值