2015-06-17 27 views
1

我正在瀏覽Go Bootcamp並正在閱讀Go Concurrency章節。我從來沒有在編程中使用併發之前,不明白這個程序的輸出:爲什麼我的併發函數在Go中過早退出?

package main 

import (
    "fmt" 
    "time" 
) 

func say(s string) { 
    for i := 0; i < 2; i++ { 
     time.Sleep(100 * time.Millisecond) 
     fmt.Println(s) 
    } 
} 

func main() { 
    go say("world") 
    say("hello") 
} 

輸出:

hello 
world 
hello 

Program exited. 

有人能解釋爲什麼「世界」沒有印像兩次「你好」 ?也許闡明使用併發的想法?

注意,Go遊樂場鏈接here

回答

4

Go主程序退出時會退出。在這種情況下,您的程序不會等待最後的「世界」在退出之前在另一個goroutine中打印。

以下代碼(playground)將確保main不會退出,從而允許另一個goroutine完成。

package main 

import (
    "fmt" 
    "time" 
) 

func say(s string) { 
    for i := 0; i < 2; i++ { 
     time.Sleep(100 * time.Millisecond) 
     fmt.Println(s) 
    } 
} 

func main() { 
    go say("world") 
    say("hello") 
    select{} 
} 

正如您可能已經注意到的,這會導致死鎖,因爲程序無法前進。您可能希望添加一個通道或sync.Waitgroup,以確保程序在另一個goroutine完成後立即退出。

例如(playground):

func say(s string, ch chan<- bool) { 
    for i := 0; i < 2; i++ { 
     time.Sleep(100 * time.Millisecond) 
     fmt.Println(s) 
    } 

    if ch != nil { 
     close(ch) 
    } 
} 

func main() { 
    ch := make(chan bool) 
    go say("world", ch) 
    say("hello", nil) 
    // wait for a signal that the other goroutine is done 
    <-ch 
}