初始化项目

This commit is contained in:
皮蛋13361098506
2025-01-06 16:01:02 +08:00
commit 1b77f62820
575 changed files with 69193 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
// Package routineCtrlUtil
//
// @description: 协程控制-用于海量循环中,限制并发的最大同时执行协程数
// @author:
// @revision history:
// @create date: 2022-02-23 17:23:06
package routineCtrlUtil
import "sync"
// RoutineCtrl
//
// @description: 控制同时运行的协程数
type RoutineCtrl struct {
wg *sync.WaitGroup
chNum chan struct{}
}
// Run
//
// @description: 循环内待执行的协程封装在f函数参数内执行。f函数的最大并发运行数受New参数maxNum限制
// 注意:*** 待执行函数引用外变变量,程序可能会出现不符合逻辑的结果(外部变量变化时,闭包函数获取到的是变化后的变量值) ***
// *** 闭包函数避坑说明 ***
// 方式1)将待执行函数内使用的外部变量,用参数传入,可避免不符合逻辑的结果
// 方式2)将待执行函数内使用的外部变量,使用一个临时局部变量将其值“固定”下来,闭包内使用临时局部变量(临时局部变量不会再被修改)
// 示例routine_ctrl_test.go -> TestRoutineCtrl
//
// parameter:
//
// @receiver rtCtrl:
// @f: 循环内待执行的协程
//
// return:
func (rtCtrl *RoutineCtrl) Run(f func(interface{}), arg interface{}) {
rtCtrl.wg.Add(1)
rtCtrl.chNum <- struct{}{}
go func() {
defer func() {
<-rtCtrl.chNum
rtCtrl.wg.Done()
recover() // 异常捕获
}()
f(arg) // 调用实际函数体
}()
}
// Wait
//
// @description: 在循环外面等待所有协程执行结束后返回
//
// parameter:
//
// @receiver rtCtrl:
//
// return:
func (rtCtrl *RoutineCtrl) Wait() {
rtCtrl.wg.Wait()
}
// New
//
// @description: 产生一个协程控制对象
//
// parameter:
//
// @maxNum: 限制调用Run时的f函数的最大运行协程数
//
// return:
//
// @*RoutineCtrl:
func New(maxNum int) *RoutineCtrl {
return &RoutineCtrl{
wg: &sync.WaitGroup{},
chNum: make(chan struct{}, maxNum),
}
}

View File

@@ -0,0 +1,48 @@
package routineCtrlUtil
import (
"fmt"
"testing"
"time"
)
func TestRoutineCtrl(t *testing.T) {
rtCtrl := New(3)
for i := 0; i < 10; i++ {
// 闭包函数避坑注意!!!
// 本段代码有坑,请特别注意!!!
// *** 待执行函数引用外变变量i程序可能会出现不符合逻辑的结果(外部变量变化时,闭包函数获取到的是变化后的变量值) ***
//rtCtrl.Run(func(arg interface{}) {
// fmt.Println(".", i)
// time.Sleep(time.Second * 1)
// fmt.Println("*", i)
// panic("111")
//}, nil)
//-------------------------------------------------
// 以下两种方式为正确示例:
// 避坑方式一:将闭包内使用的外部变量作为参数传入
// 将待执行函数内使用的外部变量,用参数传入,可避免不符合逻辑的结果
//rtCtrl.Run(func(arg interface{}) {
// ii, _ := arg.(int)
// fmt.Println(".", ii)
// time.Sleep(time.Second * 1)
// fmt.Println("*", ii)
// panic("111")
//}, i)
// 避坑方式二:将闭包内使用的外部变量固定下来,不让其再被修改
temp := i // 这种方式将产生一个局变变量temp并且temp不会被修改
rtCtrl.Run(func(arg interface{}) {
fmt.Println(".", temp)
time.Sleep(time.Second * 1)
fmt.Println("*", temp)
panic("111")
}, nil)
}
rtCtrl.Wait()
fmt.Println("\n==============")
}