在golang中,我們可以很輕易產生數以萬計的goroutine,不過這也帶來了麻煩:在運行中某一個goroutine異常退出,怎么辦?
在erlang中,有link原語,2個進程可以鏈接在一起,一個在異常退出的時候,向另一個進程呼喊崩潰的原因,然后由另一個進程處理這些信號,包括是否重啟這個進程。在這方面,erlang的確做得很好,估計以后這個特性會在golang中得到實現。
由此得到啟發,我寫了一個簡單的程序,監控goroutine異常退出。
package main import ( "log" "runtime" "math/rand" "time" ) type message struct { normal bool //true means exit normal, otherwise state map[string]interface{} //goroutine state } func main() { runtime.GOMAXPROCS(runtime.NumCPU()) mess := make(chan message, 10) for i := 0; i < 100; i++ { go worker(mess) } supervisor(mess) } func worker(mess chan message) { defer func() { exit_message := message{state:make(map[string] interface{})} i := recover() if i != nil { exit_message.normal = false } else { exit_message.normal = true } mess <- exit_message }() now := time.Now() seed := now.UnixNano() rand.Seed(seed) num := rand.Int63() if num % 2 != 0 { panic("not evening") } else { runtime.Goexit() } } func supervisor(mess chan message) { for i := 0; i < 100; i++ { m := <- mess switch m.normal { case true : log.Println("exit normal, nothing serious!") case false: log.Println("exit abnormal, something went wrong") } } }
原本是想把goroutine異常退出時的狀態,也就是某些變量保存到message中的state,然后在另一個goroutine里面處理這些數據,不過能力有限,暫時做不出來,以后會完善的。這里只驗證goroutine在異常退出的時候,向另一個goroutine發送信號。
在worker函數里面,會判斷隨機數是不是偶數,不是的話會使用panic異常退出,然后使用defer向supervisor發送信號,supervisor接受到就輸出結果。
下面看一下效果:

我們用了100個goroutine,也就有100個退出信號。由圖可以得到我們的程序運行良好。
轉貼請注明來自:格通
