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

时间:2015-07-23 20:07:43

标签: linux macos go

这个例子取自“A Tour of Go”:https://tour.golang.org/concurrency/1

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

但我们有:

  • 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")
}

1 个答案:

答案 0 :(得分:2)

来自the specification

  

程序执行从初始化主包然后调用函数main开始。当该函数调用返回时,程序退出。它不会等待其他(非main)goroutines完成。

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

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

您可以通过使主goroutine明确等待其他goroutine的完成来修复它。例如,使用频道:

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
}

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

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