2 回答

TA貢獻1827條經(jīng)驗 獲得超8個贊
函數(shù)調(diào)用和 goroutines 不能被調(diào)用者終止,函數(shù)和 goroutines 必須支持取消,通常通過context.Context值或done通道。
在任何一種情況下,函數(shù)都負責檢查/監(jiān)視上下文,如果請求取消(當上下文的完成通道關(guān)閉時),則提前返回。沒有更簡單/自動的方法。
如果任務在循環(huán)中執(zhí)行代碼,一個方便的解決方案是在每次迭代中檢查完成的通道,如果它關(guān)閉則返回。如果任務是一個“整體”,則實現(xiàn)者負責使用/插入“檢查點”,如果請求取消,則可以合理地提前中止任務。
檢查 done 通道是否關(guān)閉的一種簡單方法是使用 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()永遠選擇)。在這種情況下,您可以結(jié)合上述 2:首先對取消進行非阻塞檢查,然后將 aselect與您的通道操作和取消監(jiān)控一起使用。

TA貢獻1752條經(jīng)驗 獲得超4個贊
當我們談到取消時,我們談到了一個長期運行的函數(shù)或一個重復多次的塊,例如http.Serve()
至于您的情況,假設(shè)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 關(guān)注
- 139 瀏覽
添加回答
舉報