为什么我的并发函数在Go中过早退出?

时间:2015-06-17 00:28:30

标签: concurrency go

我正在浏览Go Bootcamp并正在阅读Go Concurrency章节。我在编程之前从未使用过并发,并且不了解该程序的输出:

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.

有人可以解释为什么&#34;世界&#34;不打印两次像&#34;你好&#34;?也许可以阐明使用并发的想法?

注意,转到游乐场链接here

1 个答案:

答案 0 :(得分:4)

当主程序返回时,Go程序退出。在这种情况下,您的程序不会等待最终的&#34;世界&#34;在退出之前在另一个goroutine上打印。

以下代码(playground)将确保主要永不退出,允许其他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
}