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

标签 concurrency go

<分区>

我正在浏览 Go Bootcamp,现在正在阅读 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.

有人能解释一下为什么“world”不像“hello”那样打印两次吗?也许阐明使用并发的想法?

注意,Go Playground 链接 here .

最佳答案

Go 程序在 main 返回时退出。在这种情况下,您的程序在退出之前不会等待最终的“世界”在另一个 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{}
}

您可能已经注意到,这会导致死锁,因为程序无法继续前进。您可能希望添加一个 channel 或一个 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
}

关于concurrency - 为什么我的并发函数在 Go 中过早退出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30880419/

相关文章:

Python 多处理/套接字 - 错误的文件描述符

inheritance - 如何在 Golang 中为多种类型编写一个函数?

阻止接收 channel

go - 限制运行的例程数量

go - 第二个bufio.Scanner for stdin不读取任何内容

go - 页面完全加载后如何重定向到另一个页面

go - go.mod 中的 golang.org/x/sys@hash 版本被忽略

java - 仅当条件为真且多线程时才应调用函数

java - JavaFx并发事件

go - 当我尝试模拟扇入时陷入僵局 - 通过阶乘计算扇出