天天看點

「讓我們一起Golang」讓協程自己kill自己

「讓我們一起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

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()

激活,讓他能夠運作。

看看運作結果吧。

任務進行中...
任務進行中...
...(中間省略若幹)
任務進行中...           

部落客等了半分鐘,子協程一直在那大喊“任務進行中...”,像極了晚上父母不在家,大喊大叫的熊孩子。