linux - go1.5beta2 在 MacOS 和 Linux 上的不同行为

标签 linux macos go

例子取自《围棋之旅》:https://tour.golang.org/concurrency/1

显然,程序输出应该有 10 行:5 行用于“hello”,5 行用于“world”。

但是我们有:

  • Linux - 9 行
  • MacOS - 10 行

Linux 输出(9 行):

$ go run 1.go 
hello
world
hello
world
hello
world
world
hello
hello

MacOS X 输出(10 行):

$ go run 1.go 
hello
world
world
hello
hello
world
hello
world
hello
world

谁能解释一下 - 为什么

Linux uname -a:

Linux desktop 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1 (2015-05-24) x86_64 GNU/Linux

MacOS X uname -a:

Darwin 14.5.0 Darwin Kernel Version 14.5.0: Thu Jul  9 22:56:16 PDT 2015; root:xnu-2782.40.6~1/RELEASE_X86_64 x86_64

旅游源代码:

package main

import (
    "fmt"
    "time"
)

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

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

最佳答案

来自 the specification :

Program execution begins by initializing the main package and then invoking the function main. When that function invocation returns, the program exits. It does not wait for other (non-main) goroutines to complete.

因此无法保证 goroutine 打印 "world" 有时间在程序退出之前完成。

我怀疑如果您运行该程序足够多次,您将在两个平台上同时看到 9 行和 10 行输出。将 GOMAXPROCS 环境变量设置为 2 也可能有助于触发问题。

您可以通过让主 goroutine 显式等待另一个 goroutine 完成来修复它。例如,使用 channel :

func say(s string, done chan<- bool) {
    for i := 0; i < 5; i++ {
        time.Sleep(1000 * time.Millisecond)
        fmt.Println(s)
    }
    done <- true
}

func main() {
    c := make(chan bool, 2)
    go say("world", c)
    say("hello", c)
    <-c
    <-c
}

我已经向 channel 添加了一个缓冲区,以便 say 函数可以发送一个值而不阻塞(主要是 "hello" 调用实际返回)。然后我等待从 channel 接收两个值以确保两个调用都已完成。

对于更复杂的程序,sync.WaitGroup type 可以提供一种更方便的方式来等待多个 goroutines。

关于linux - go1.5beta2 在 MacOS 和 Linux 上的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31597096/

相关文章:

java - 将 .Jar 转换为 .Dmg

go - BufferedWriter 在同时使用时不起作用

go - 如何使用命令行在 linux 中使用 ffmpeg 将两个 wav 拼接在一起?

python - djcelery、billiard 和 django_settings_module 的异常警告

linux - linux环境下使用php的web服务

xcode - 命令行工具的静态分析问题

objective-c - 如何在后台线程上执行长时间操作,然后在主线程上更新 UI

go - 私有(private)仓库 - go 1.13 - `go mod ..` 失败 : ping "sum.golang.org/lookup" . 。正在验证包.. 410 消失了

c# - 从 asp.net 核心应用程序启动 linux 进程失败(找不到文件)

linux - 在 Jenkins 中执行 shell 命令不识别管道字符