【发布时间】:2016-03-05 05:07:48
【问题描述】:
不,不是因为我的程序结束得太快了。
我有这个脚本:
package main
import ("log"; "io/ioutil"; "strings")
const BASE_FILE_NAME = "abc_"
func mygoroutine(file_name string) {
log.Println("In goroutine for file", file_name)
}
func get_file_names() []string {
file_names := make([]string, 0)
files, _ := ioutil.ReadDir("./")
for _, file := range files {
if strings.HasPrefix(file.Name(), BASE_FILE_NAME) {
file_names = append(file_names, file.Name())
}
}
return file_names
}
func main() {
file_names := get_file_names()
for _, file_name := range file_names {
log.Println("Now lunching goroutine for file", file_name)
go mygoroutine(file_name)
}
log.Println("Finished launching.")
for {}
log.Println("Now exiting")
}
在包含可执行文件的目录中,我有两个以abc_ 开头的文件,所以输出是这样的:
2016/03/04 20:35:14 Now lunching goroutine for file abc_fr
2016/03/04 20:35:14 Now lunching goroutine for file abc_hrty
2016/03/04 20:35:14 Finished launching.
脚本不会停止,它永远不会记录 Now exiting ,因为它在空的 for 中循环。但我没有看到In goroutine for file 消息。
为什么会这样?我做错了什么?
感谢您的帮助!
【问题讨论】:
-
如果
GOMAXPROCS=1,for{}冻结你的程序,而不会让它切换 goroutines。select{}不这样做也不吃 CPU。 -
您可以使用
WaitGroup代替for {}循环 - 请参阅 nathanleclaire.com/blog/2014/02/15/… -
是的,我认为你是对的。在看到您的评论之前,我用 time.Sleep() 更改了 for {} 并且它起作用了。我现在将更改 GOMAXPROCS,看看会发生什么。
-
实际上,即使 GOMAXPROCS>1
for{}最终会在 GC 尝试停止世界时完全阻塞调度程序。永远不要使用繁忙的循环。 -
查看这个答案stackoverflow.com/a/34885000/2363866 也许谷歌关于 go scheduler,有一些很棒的博客文章和 golang 团队设计文档。其实并不像
busy loop freezes your program那么简单。它在某些情况下可能会冻结,在其他情况下,即使使用 GOMAXPROCS=1 并且没有阻塞操作,它也可以工作。