「让我们一起Golang」让协程自己kill自己

举报
Regan Yue 发表于 2021/08/15 09:49:02 2021/08/15
【摘要】 「让我们一起Golang」让协程自己kill自己我们这篇博文讨论Go的协程杀掉自己协程的有关内容。这里我们就需要用到runtime.Goexit().先上代码介绍runtime.Goexit()及其使用方法package mainimport ( "fmt" "runtime" "time")func task051() { defer fmt.Println("拿来吧你") fmt.P...

「让我们一起Golang」让协程自己kill自己

我们这篇博文讨论Go的协程杀掉自己协程的有关内容。这里我们就需要用到runtime.Goexit().

先上代码介绍runtime.Goexit()及其使用方法

package main

import (
	"fmt"
	"runtime"
	"time"
)

func task051()  {
	defer fmt.Println("拿来吧你")

	fmt.Println("曲项向天歌")
	fmt.Println("白毛浮绿水")
	//杀死当前所在协程
	// Goexit terminates the goroutine that calls it. No other goroutine is affected.
	// Goexit runs all deferred calls before terminating the goroutine. Because Goexit
	// is not a panic, any recover calls in those deferred functions will return nil.
	//
	// Calling Goexit from the main goroutine terminates that goroutine
	// without func main returning. Since func main has not returned,
	// the program continues execution of other goroutines.
	// If all other goroutines exit, the program crashes.
	runtime.Goexit()

	fmt.Println("红掌拨清波")
}

func main() {
	go func() {
		fmt.Println("鹅鹅鹅")
		task051()
		fmt.Println("——骆宾王")
	}()
	// Sleep pauses the current goroutine for at least the duration d.
	// A negative or zero duration causes Sleep to return immediately.
	time.Sleep(time.Second)
}

如果Goexit杀掉它的 goroutine,其他 goroutine 也不会受到影响。 Goexit在终止 goroutine 之前会调用所有延迟函数, 因为 Goexit不是一个panic,而这些延迟函数中的任何调用恢复都将返回 nil。
从主协程调用 Goexit会终止主协程,而不会返回主函数func main。 由于 主函数func main 没有返回,程序会继续执行其他 goroutine。 如果所有其他 goroutine 都终止,那么程序就会崩溃。

在这段代码里面,主函数中是先开辟一条协程,先输出《咏鹅》的第一句诗句,然后进入任务函数。该任务函数是执行在子协程中。

这段代码的运行结果是

鹅鹅鹅
曲项向天歌
白毛浮绿水
拿来吧你

这里“红掌拨清波”并没有输出,因为它是在runtime.Goexit()之后的语句,而此时协程已经被自己杀死了。

但是延迟函数被执行了,Goexit在终止 goroutine 之前会调用所有延迟函数, 因为 Goexit不是一个panic,而这些延迟函数中的任何调用恢复都将返回 nil。所以“拿来吧你”不会输出。

但是作者名”——骆宾王“为什么也没输出呢?思考一下吧。

因为函数task051()里面将当前协程kill掉了。而作者名”——骆宾王“因为协程已经被杀死而执行不到。

前面杀死的是子协程。

我们之前说主协程不能死,那么我们现在杀死主协程看看会怎么样吧!

主协程被杀死之后,所有子协程就会乱了套,不眠不休。

我们先来看看主协程正常结束的样子吧…

func main() {
	go task061()
	//主协程睡5秒
	time.Sleep(5 * time.Second)

	//runtime.Goexit()
}
func task061(){
	for{
		fmt.Println("任务进行中...")
		time.Sleep(time.Second)
	}
}

运行结果是:

任务进行中...
任务进行中...
任务进行中...
任务进行中...
任务进行中...

主协程睡觉睡了5秒,子协程没睡一秒就说一句“任务进行中…”,所以当主协程结束时,主协程说五句“任务进行中…”。

现在我们杀死主协程看看会出现什么吧!

将上面代码块的runtime.Goexit()激活,让他能够运行。

看看运行结果吧。

任务进行中...
任务进行中...
...(中间省略若干)
任务进行中...

博主等了半分钟,子协程一直在那大喊“任务进行中…”,像极了晚上父母不在家,大喊大叫的熊孩子。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。