2015-06-17 22 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 
}