這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
今天遇到一個問題(應該算是坑吧):
在Goroutine中退出時defer調用RPC的Close函數, 但是server總是提示網路非正常退出.
最終發現是Goroutine退出時調用Close可能導致阻塞, 阻塞導致Goroutine切換到main.
main 退出後程式就終止了.
我構造了一個類似的例子:
package mainimport ( "log" "time")func worker(quit <-chan bool) { defer func() { // 如果被調用函數內部可能阻塞的話 // 將不能保證被完全執行 time.Sleep(time.Second) log.Println("worker clean up") }() for { select { case <-quit: log.Println("worker quit ...") return default: } }}func main() { quit := make(chan bool) go worker(quit) quit <- true}
我目前想到的安全做法是: 再設定一個done管道, 在main函數中阻塞等待Goroutine清理工作全部完成.
更好的等待Goroutine完成的方法是用sync.WaitGroup:
"http://www.golang.org/",// using a WaitGroup to block until all the fetches are complete.func ExampleWaitGroup() { var wg sync.WaitGroup var urls = []string{ "http://www.golang.org/", "http://www.google.com/", "http://www.somestupidname.com/", } for _, url := range urls { // Increment the WaitGroup counter. wg.Add(1) // Launch a goroutine to fetch the URL. go func(url string) { // Decrement the counter when the goroutine completes. defer wg.Done() // Fetch the URL. http.Get(url) }(url) } // Wait for all HTTP fetches to complete. wg.Wait()}
關於sync.WaitGroup文檔請參考: http://golang.org/pkg/sync/#WaitGroup