package main
import (
"fmt"
"time"
)
func main() {
// 業務邏輯
// 假設目前的業務需要循環對array進行指派
var array []int
startParam := 0
doneChan := make(chan struct{}, 1) // channel通知任務完成
NoCircleRange(doneChan, time.Second*5, func() { // 安全的循環
/*****業務邏輯 (循環體)****/
array = append(array, startParam)
startParam++
// 循環退出條件
if startParam == 10 {
doneChan <- struct{}{}
}
})
// 業務執行完成 繼續處理
fmt.Println(array)
}
// NoCircleRange 防止for循環出現死循環
/******
* fun 函數應該是循環體内容
* 循環體應保證不會阻塞
* fun 函數體應該由業務邏輯和退出條件兩部分組成
*/
func NoCircleRange(done chan struct{}, maxExec time.Duration, fun func()) {
signChan := time.After(maxExec)
for {
fun()
select {
case <-signChan: // 執行逾時
panic("[NoCircleRange] func execute time out")
case <-done: // 函數執行完成
// channel 資源在沒有被goroutine引用時,會自動被GC回收 無關是否關閉
// 關閉channel可以通知到使用此channel的goroutine 此場景下無需通知
close(done)
return
default:
continue
}
}
}