2 回答

TA貢獻1827條經驗 獲得超8個贊
函數調用和 goroutines 不能被調用者終止,函數和 goroutines 必須支持取消,通常通過context.Context值或done通道。
在任何一種情況下,函數都負責檢查/監視上下文,如果請求取消(當上下文的完成通道關閉時),則提前返回。沒有更簡單/自動的方法。
如果任務在循環中執行代碼,一個方便的解決方案是在每次迭代中檢查完成的通道,如果它關閉則返回。如果任務是一個“整體”,則實現者負責使用/插入“檢查點”,如果請求取消,則可以合理地提前中止任務。
檢查 done 通道是否關閉的一種簡單方法是使用 non-blocking select,例如:
select {
case <-ctx.Done():
// Abort / return early
return
default:
}
當任務使用其他通道操作時必須小心,因為它們可能會以不確定的方式阻塞。這些選擇也應該包括ctx.Done()頻道:
select {
case v := <- someChannel:
// Do something with v
case <-ctx.Done():
// Abort / return early
return
}
還要小心,因為如果上面的 receive from someChannelnever 阻塞,則不能保證正確處理取消,因為如果多個通信可以在 a 中進行select,則隨機選擇一個(并且不能保證<-ctx.Done()永遠選擇)。在這種情況下,您可以結合上述 2:首先對取消進行非阻塞檢查,然后將 aselect與您的通道操作和取消監控一起使用。

TA貢獻1752條經驗 獲得超4個贊
當我們談到取消時,我們談到了一個長期運行的函數或一個重復多次的塊,例如http.Serve()
至于您的情況,假設saveChunk運行將花費幾秒鐘,并且您想在保存時取消。所以我們可以把塊分成幾塊,在每一塊之后一個接一個地保存。
for i:=0;i<n;i++{
select {
case err := <- s.saveChunk(chunk[i]):
{
if err != nil {
fmt.Errorf("failed saving chunk %w", err)
return
}
}
case <-ctx.Done():
return
}
}
- 2 回答
- 0 關注
- 133 瀏覽
添加回答
舉報