下面的代码段
package main
import (
"fmt"
"runtime"
)
func main() {
runtime.GOMAXPROCS(1)
var s string
done := make(chan bool)
go func() {
fmt.Scanln(&s)
fmt.Println(s)
done <- true
}()
var i int
for i = 0; i < 1e10; i++ {
}
fmt.Println(i)
<-done
}
运行它,快速输入几个字符,例如abcd
循环结束前的for
;最后点击Enter
。据我所知,for
循环中没有Gosched
可以将主goroutine切换到子例程的屈服点,为什么迅速打印abcd
甚至在for
循环结束之前?
abcd10000000000
abcd
答案 0 :(得分:1)
您无法预测输出是随机的。因为在您的情况下,go例程将运行,然后执行for循环。现在,如果go例程在for循环完成其迭代之前完成,则它将首先在go例程中打印该值,然后在done
通道上发送该值,然后它将打印i
的值。 done
通道将等待,直到go例程在其上发送了值。
例如,如果您尝试仅扫描as
然后快速输入,则您的值将首先在go例程中打印,然后10000000000
将在最后一个例程中打印,因此取决于go例程是否将在执行之前执行for循环完成。
运行时可以分配比GOMAXPROCS
的值更多的线程来服务多个未完成的I / O请求。 GOMAXPROCS
仅影响一次实际可以执行多少个goroutine;系统调用中可能会任意阻止更多内容。
答案 1 :(得分:0)
代码按预期运行,
每个正在运行的程序都可以访问三个文件,stdin
,stdout
,stderr
。
您在终端中键入的所有内容都是您写入stdin
文件,程序输出也写入stdout
。
在您的情况下,您已将一些数据写入stdin
,正在读取和显示。
如果您甚至在进程开始处理输入之前就已经写了一些数据,那也是一样,从文件读取。
基本上,只要程序启动并获得足够的输入,它就会继续进行,如果它没有机会执行,直到有人读取输入,它仍然位于stdin
中。
由于GOMAXPROCS
并不意味着您将只运行一个goroutine,如果该goroutine被阻止,则会创建一个新的goroutine。 GOMAXPROCS
表示在任何时间实例中只能运行一个用户线程。