Go語言通知協程退出(取消)的幾種方式 - 知乎
GoLang之goroutine底層系列二(goroutine的創建、讓出、恢復)_golang goroutine-CSDN博客
在 Go 語言中,協程(也稱為 goroutine)是通過?go
?關鍵字啟動的輕量級線程。由于 goroutine 的調度是由 Go 運行時管理的,直接停止一個正在執行的 goroutine 是不可能的,這與操作系統線程不同。但是,你可以通過一些策略來實現“中斷”和“恢復”的行為,盡管這不是傳統意義上的停止和恢復。
1. 使用通道(Channel)進行信號傳遞
最常用的方法是使用通道(channel)來安全地中斷 goroutine。你可以在另一個 goroutine 中向該 goroutine 發送一個信號(例如,一個特殊的值或者一個結構體),然后在被中斷的 goroutine 中定期檢查這個通道以決定是否退出循環或函數。
package mainimport ("fmt""time"
)func worker(done chan bool) {for {select {case <-done:fmt.Println("Worker stopped.")return // 退出函數,結束 goroutinedefault:fmt.Println("Working...")time.Sleep(500 * time.Millisecond) // 模擬工作}}
}func main() {done := make(chan bool)go worker(done)time.Sleep(2 * time.Second) // 等待一段時間done <- true // 發送信號到 worker,要求它停止time.Sleep(1 * time.Second) // 等待 worker 完全停止
}
2. 使用 context 包
context
?包是 Go 標準庫中處理請求范圍的值、取消信號和截止時間的標準方式。它非常適合用來控制 goroutine 的生命周期。
示例代碼:
package mainimport ("context""fmt""time"
)func worker(ctx context.Context) {for {select {case <-ctx.Done(): // 當 ctx 被取消時,這里會被觸發fmt.Println("Worker stopped.")return // 退出函數,結束 goroutinedefault:fmt.Println("Working...")time.Sleep(500 * time.Millisecond) // 模擬工作}}
}func main() {ctx, cancel := context.WithCancel(context.Background())go worker(ctx)time.Sleep(2 * time.Second) // 等待一段時間cancel() // 取消 context,要求 worker 停止time.Sleep(1 * time.Second) // 等待 worker 完全停止
}
3. 使用 sync.Once 或 sync.Mutex 控制退出邏輯的執行一次
如果你需要在某些情況下只安全地執行退出邏輯一次,可以使用?sync.Once
?來確保。這對于確保資源清理代碼只運行一次非常有用。但是,這種方法更多地是關于如何安全地執行退出邏輯,而不是真正地“中斷”一個正在執行的 goroutine。
示例代碼:
package mainimport ("fmt""sync""time"
)var once sync.Once
var running = true // 控制循環是否繼續運行的標志位func worker() {for running { // 使用 running 作為循環條件來控制何時退出循環體中的代碼塊。fmt.Println("Working...")time.Sleep(500 * time.Millisecond) // 模擬工作}
}func stopWorker() { // 安全地停止 worker 的函數。使用 sync.Once 確保只調用一次。once.Do(func() { // 使用 sync.Once 來確保這個操作只執行一次。running = false // 設置 running 為 false,讓循環在下次迭代時退出。})
}
在上面的代碼中,你可以通過調用?stopWorker()
?來停止?worker()
?函數。但是,這種方法更多地是控制何時退出循環而不是真正地“中斷”一個正在執行的 goroutine。在實踐中,通常推薦使用通道或 context 來管理 goroutine 的生命周期。