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
}
}
}