2017-05-08 17 views
2

當上下文變量超出範圍並且未明確調用cancel時,context.Done()會解鎖嗎?當上下文變量超出golang的範圍時,Context.Done()是否解鎖?

比方說,我有以下代碼:

func DoStuff() { 
    ctx, _ := context.WithCancel(context.Background()) 
    go DoWork(ctx) 
    return 
} 

威爾ctx.Done()取消阻止的DoWork在DoStuff迴歸後的()?

我找到了這個線程https://groups.google.com/forum/#!topic/golang-nuts/BbvTlaQwhjw,在那裏詢問如何使用Context.Done()的人聲稱,context.Done()將在上下文變量離開範圍時解除阻塞,但沒有人驗證過這一點,而且我沒有看到文檔中的任何內容。

+0

我想你認爲這個人只是在問一個關於它是否被自動取消而不是聲稱任何東西的問題。 –

回答

5

不,它不會在上下文離開範圍時自動取消。通常會自動調用defer cancel()(使用ctx.WithCancel()的回調)以確保取消上下文。

https://blog.golang.org/context提供了關於如何正確使用上下文的良好概述(包括上面的defer模式)。此外,源代碼https://golang.org/src/context/context.go非常易讀,您可以看到沒有任何魔法可以提供自動取消功能。

2

「暢通」並不是最清楚的術語。 Done()返回將會收到struct{}和/或當上下文被「取消」時關閉的頻道(或無)。究竟是什麼,或者什麼時候發送,都取決於個體的實現。它可以在某個固定時間發送/關閉,如WithDeadline,或手動完成,如WithCancel

但關鍵是,這絕不是「自動」或保證發生。如果您使用WithCancel作爲上下文並從Done()通道讀取,則該讀取將無限期地阻止,直到調用Cancel()方法。如果這種情況永遠不會發生,那麼你有一個浪費的goroutine,你的應用程序的內存每次增加時都會增加。

一旦上下文完全超出範圍(沒有正在執行的goroutine正在監聽它或對父上下文有引用),它將被垃圾收集,一切都會消失。

編輯:雖然看完源代碼後,看起來像WithCancel和朋友產卵goroutines,以推定取消。因此,您必須必須確保取消某些時候被調用,以避免goroutine泄漏。