因此,如果某些事情花費的時間太長,我會嘗試關閉長時間運行的功能,這可能只是治療癥狀而不是原因的解決方案,但無論如何,對于我的情況,它并沒有真正解決。
我是這樣做的:
func foo(abort <- chan struct{}) {
for {
select{
case <-abort:
return
default:
///long running code
}
}
}
在單獨的函式中,我有一段時間后關閉傳遞的鏈,如果我切割主體回傳函式,它會這樣做。但是,如果有一些長時間運行的代碼,它不會影響結果,它只是繼續作業,就好像什么都沒發生一樣。
我對 GO 還很陌生,但感覺它應該可以作業,但事實并非如此。有什么我想念的嗎。在所有路由器框架都有超時功能之后,任何正在運行的東西都會被終止。所以也許這只是出于好奇,但我真的很想知道怎么做。
uj5u.com熱心網友回復:
在您的“長期運行代碼”中,您必須定期檢查該abort頻道。
“定期”實作這一點的常用方法是將代碼分成塊,每個塊在相當短的時間內完成(假設運行行程的系統沒有過載)。
在執行每個這樣的塊后,您檢查終止條件是否成立,如果是則終止執行。
執行此類檢查的慣用方法是“ selectwith default”:
select {
case <-channel:
// terminate processing
default:
}
在這里,如果還沒有準備好接收(或關閉)default無操作分支,則立即采用無操作分支。channel
一些演算法使這種分塊更容易,因為它們采用了一個回圈,每次迭代都需要大致相同的時間來執行。如果您的演算法不是這樣,您必須手動對其進行分塊;在這種情況下,最好為每個塊創建一個單獨的函式(或方法)。
進一步的點。
考慮使用背景關系:它們提供了一個有用的框架來解決您正在解決的問題的風格。
更好的是,他們可以“繼承”彼此這一事實允許一個人輕松實作兩件整潔的事情:
- 您可以結合各種方式來取消背景關系:例如,可以創建一個背景關系,該背景關系在某些超時過去或由其他代碼顯式取消時被取消。
- 它們使得創建“取消樹”成為可能——當取消根背景關系時將此信號傳播到所有繼承背景關系——使它們取消其他 goroutine 正在執行的操作。
有時,當人們說“長時間運行的代碼”時,他們并不是指實際上一直在 CPU 上處理數字的代碼,而是指對慢速物體(例如資料庫、HTTP 服務器等)執行請求的代碼,在這種情況下代碼實際上并沒有運行,而是在 I/O 上休眠以傳遞一些要處理的資料。
如果是這種情況,請注意所有撰寫良好的 Go 包(當然,這包括 Go 標準庫中處理網路服務的所有包)在其 API 的那些函式中接受背景關系,這些函式實際上呼叫了如此慢的物體,這意味著如果你讓你的函式接受一個背景關系,你可以(實際上應該)將此背景關系傳遞到適用的呼叫堆疊中——這樣你呼叫的所有代碼都可以像你的一樣被取消。
進一步閱讀:
- https://go.dev/blog/pipelines
- https://blog.golang.org/advanced-go-concurrency-patterns
uj5u.com熱心網友回復:
在執行長時間運行的代碼之前,您的代碼僅在每次迭代時檢查通道是否關閉一次。長時間運行的代碼開始后沒有機會檢查abortchan,因此它將運行到完成。
您需要偶爾檢查是否在長時間運行的代碼主體中提前退出,這更習慣使用context.Context例如WithTimeout:https ://pkg.go.dev/context#example-WithTimeout
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/505075.html
標籤:去
上一篇:jquery/javascript回圈值和optgroup
下一篇:io.Pipe使用困難
