天天看点

golang 避免程序出现死循环

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