go lang,为什么日常功能从未被调用过

时间:2015-04-15 15:26:36

标签: go

package main

import (
    "fmt"
    //"runtime"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        //runtime.Gosched()
        fmt.Println(s)
    }
}

func main() {
    go say("world") // create a new goroutine
    say("hello") // current goroutine
}

为什么结果是:

您好 你好 你好 你好 喂

为什么没有&#39;世界&#39;

答案:(编辑:) 如果我这样做,现在好了:

package main

import (
    "fmt"
    "runtime"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        //runtime.Gosched()
        fmt.Println(s)
    }
}

func main() {
    go say("world") // create a new goroutine
    runtime.Gosched()

    say("hello") // current goroutine
}

3 个答案:

答案 0 :(得分:2)

您只是遇到了时间问题,因为您没有“协调”您的日程安排。解决这个问题的常见方法是使用等待守卫。我不时使用频道和阻止选择看到的另一个选项。等待守卫的实施看起来像这样;

func main() {
    wg := sync.WaitGroup{}
    wg.Add(1)
    go say("world") // create a new goroutine

    wg.Add(1)
    say("hello") // current goroutine
    wg.Wait()
}

虽然频道选项(在这个例子中实际上没有意义或有用)更像是这样;

 func main() {
    done := make(chan bool)
    go say("world", done) // create a new goroutine

    say("hello", done) // current goroutine

    select {
        case fin := <- done:
           //on finished
           return
    }
}

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

通过上面的例子,第一个说完成的调用将允许程序完成执行。为了确保两者都完成,您必须向每个通道传递不同的通道,并在两者上都有阻塞读取。这更像是一种模式,当你的例行程序正在进行实际工作时你会想要使用数据来汇总数据或需要更复杂的协调(比如根据之前的结果产生新的goroutine等)。

答案 1 :(得分:1)

你不允许goroutine在main()退出之前运行。

即使第二次调用say阻塞(简要),也无法保证第一个goroutine可以运行。您需要等待两者都返回,这通常是使用WaitGroup

完成的
var wg sync.WaitGroup

func say(s string) {
    defer wg.Done()
    for i := 0; i < 5; i++ {
        //runtime.Gosched()
        fmt.Println(s)
    }
}

func main() {
    wg.Add(1)
    go say("world") // create a new goroutine

    wg.Add(1)
    say("hello") // current goroutine
    wg.Wait()
}

答案 2 :(得分:0)

这是因为主goroutine退出时间过早。当主goroutine退出时,该进程将退出,因此其他goroutine将无法运行。如果希望goroutine运行,请使主例程保持足够长的生命。

package main

import (
    "fmt"
    "runtime"
)

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

func main() {
    go say("world") // create a new goroutine
    runtime.Gosched()

    say("hello") // current goroutine
    time.Sleep(1 * time.Second) // this line
}