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
}
答案 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
}