package main
import(
"fmt"
"time"
)
func main(){
fmt.Println("1")
defer fmt.Println("-1")
go func() {
fmt.Println("2")
defer fmt.Println("-2")
time.Sleep(9 * time.Second)
}()
time.Sleep(1 * time.Second)
fmt.Println("3")
}
产生输出:1 2 3 -1 但我会认为goroutine的推迟会被称为产生:1 2 3 -2 -1
在我的实际代码中,我的goroutine被阻止在websocket上...我想我可以发送一个关闭信号,但我还没有弄清楚如何做一个等待多对象的事情(如果它实际上可以在go)完成。我正在通过将延迟-2提升到主范围来解决我的问题。
是否有一些推迟放置的技巧我做得不对?
答案 0 :(得分:5)
(我没有足够的代表发表评论?)
是的,问题在于goroutine调度并且与平台有关。使用带有goroutine的函数末尾的runtime.Gosched来确保它获得一些cputime。目前在x86_64 linux上,下面的代码将生成“3”但没有Gosched它会生成“1”:
没有。这不是问题,只能通过共同发生来解决(通过实施细节)。正如goroutine's defer not called when main scope ends中已经暗示过的那样。你的代码很活泼,因此你必须明确地同步goroutines。最简单的方法是使用频道或等待组http://golang.org/pkg/sync/#WaitGroup。哪个选项更合适取决于您正在做什么。如果您只想等待一些结果,那么让gorutine将其结果发送到频道,您只需等待它。如果你只是想等待一些goroutine,那就使用一个waitgroup。
答案 1 :(得分:2)
过程结束,因此终止内部功能。尝试在主要结束时睡觉:
func main(){
fmt.Println("1")
defer fmt.Println("-1")
go func() {
fmt.Println("2")
defer fmt.Println("-2")
time.Sleep(9 * time.Second)
}()
time.Sleep(1 * time.Second)
fmt.Println("3")
time.Sleep(9 * time.Second)
}
http://play.golang.org/p/Qrtz_0xiRs
编辑:正如评论中所提到的,这不是一般的正确方法。你应该明确地等待goroutine。
答案 2 :(得分:1)
是的,问题在于goroutine计划,并且是platform dependent。使用函数末尾的runtime.Gosched和goroutine来确保它获得一些cputime。目前在x86_64 linux上,下面的代码将生成“3”但没有Gosched它会生成“1”:
q = 1
go func() {
q = 2
defer func() { q = 3 }()
}()
runtime.Gosched()
fmt.Println(q)
答案 3 :(得分:1)
WaitGroup可以帮助您解决问题:
package main
import(
"fmt"
"sync"
"time"
)
func main(){
fmt.Println("-start main-")
defer fmt.Println("-defer main-")
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
fmt.Println("-start goroutine-")
defer fmt.Println("-defer goroutine-")
time.Sleep(2 * time.Second)
wg.Done()
}()
fmt.Println("-end main-")
wg.Wait()
}
打印:
-start main-
-end main-
-start goroutine-
-defer goroutine-
-defer main-