亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Go中沒有Goroutine的輸出

Go中沒有Goroutine的輸出

Go
喵喵時光機 2019-07-13 15:56:37
當SayHello()按預期執行,Goroutine將不打印任何內容。package mainimport "fmt"func SayHello() {     for i := 0; i < 10 ; i++ {         fmt.Print(i, " ")     }}func main() {     SayHello()     go SayHello()}
查看完整描述

3 回答

?
尚方寶劍之說

TA貢獻1788條經驗 獲得超4個贊

當你main()函數結束,您的程序也結束了。它不會等待其他的峽谷完成。

引用Go語言規范:程序執行:

程序執行從初始化主包開始,然后調用函數。main..當函數調用返回時,程序將退出。它不會等待其他的(非-main)完成的大猩猩。

看見這個答案更多細節。

你得告訴你的main()函數等待SayHello()函數開始時是一個要完成的Goroutine。您可以將它們與通道同步,例如:

func SayHello(done chan int) {
    for i := 0; i < 10; i++ {
        fmt.Print(i, " ")
    }
    if done != nil {
        done <- 0 // Signal that we're done
    }}func main() {
    SayHello(nil) // Passing nil: we don't want notification here
    done := make(chan int)
    go SayHello(done)
    <-done // Wait until done signal arrives}

另一種選擇是關閉通道,發出信號表示完成:

func SayHello(done chan struct{}) {
    for i := 0; i < 10; i++ {
        fmt.Print(i, " ")
    }
    if done != nil {
        close(done) // Signal that we're done
    }}func main() {
    SayHello(nil) // Passing nil: we don't want notification here
    done := make(chan struct{})
    go SayHello(done)
    <-done // A receive from a closed channel returns the zero value immediately}

注:

根據您的編輯/注釋:如果要運行2SayHello()函數隨機打印“混合”數字:你不能保證觀察這種行為。再次,請參閱上述答復更多細節。這個GO記憶模型只有保證某些事件發生在其他事件之前,才能保證如何執行2個并發的goroutines。

您可以嘗試它,但知道結果不會是決定性的。首先,您必須允許使用以下方法執行多個活動的goroutines:

runtime.GOMAXPROCS(2)

第二,你必須先開始SayHello()因為當前代碼首先執行SayHello()在主要的Goroutine中,只有當它完成之后,另一個就開始了:

runtime.GOMAXPROCS(2)done := make(chan struct{})go SayHello(done) 
// FIRST START goroutineSayHello(nil) 
// And then call SayHello() in the main goroutine<-done 
// Wait for completion


查看完整回答
反對 回復 2019-07-13
?
不負相思意

TA貢獻1777條經驗 獲得超10個贊

或者(對icza的回答)你可以用WaitGroup從…sync包和匿名函數以避免更改原始SayHello.

package mainimport (
    "fmt"
    "sync")func SayHello() {
    for i := 0; i < 10; i++ {
        fmt.Print(i, " ")
    }}func main() {
    SayHello()

    var wg sync.WaitGroup
    wg.Add(1)

    go func() {
        defer wg.Done()
        SayHello()
    }()

    wg.Wait()}

為了同時打印數字,在單獨的例程中運行每個print語句,如下所示

package mainimport (
    "fmt"
    "math/rand"
    "sync"
    "time")func main() {
    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(fnScopeI int) {
            defer wg.Done()

            // next two strings are here just to show routines work simultaneously
            amt := time.Duration(rand.Intn(250))
            time.Sleep(time.Millisecond * amt)

            fmt.Print(fnScopeI, " ")
        }(i)
    }

    wg.Wait()}


查看完整回答
反對 回復 2019-07-13
?
拉風的咖菲貓

TA貢獻1995條經驗 獲得超2個贊

正如其他人所提到的,當main函數返回。

一種選擇是使用類似于sync.WaitGroup在其他的峽谷里等著main在從main.

另一個選擇是runtime.Goexit()在……里面main..從戈多:

GoExit終止了調用它的Goroutine。沒有其他戈魯丁受到影響。Goexport在終止Goroutine之前運行所有延遲的呼叫。因為GoExit并不是一種恐慌,所以那些延遲函數中的任何恢復調用都會返回零。

從主Goroutine調用GoExit將終止該Goroutine,而不需要主返回。由于FuncMain尚未返回,該程序將繼續執行其他goroutines。如果其他所有的Goroutines退出,程序就會崩潰。

這允許主goroutine在后臺例程繼續執行時停止執行。例如:

package mainimport (
    "fmt"
    "runtime"
    "time")func f() {
    for i := 0; ; i++ {
        fmt.Println(i)
        time.Sleep(10 * time.Millisecond)
    }}func main() {
    go f()
    runtime.Goexit()}

這可能比永遠阻塞主函數更干凈,特別是對于無限的程序。一個缺點是,如果進程返回或退出(包括主要的goroutine)的所有循環都會檢測到這是一個錯誤和恐慌:

fatal error: no goroutines (main called runtime.Goexit) - deadlock!

為了避免這種情況,至少必須有一個Goroutine調用os.Exit在它回來之前。呼叫os.Exit(0)立即終止程序,并表示它沒有出錯。例如:

package mainimport (
    "fmt"
    "os"
    "runtime"
    "time")func f() {
    for i := 0; i < 10; i++ {
        fmt.Println(i)
        time.Sleep(10 * time.Millisecond)
    }
    os.Exit(0)}func main() {
    go f()
    runtime.Goexit()}


查看完整回答
反對 回復 2019-07-13
  • 3 回答
  • 0 關注
  • 1298 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號