go控制并发数


package main

import (
	"fmt"
	"log"
	"sync"
	"time"
)

type Glimit struct {
	n int
	c chan struct{}
}

// 初始化Glimit结构体
func New_workers(max_goroutine int) (*Glimit, error) {
	if max_goroutine <= 0 {
		return nil, fmt.Errorf("max_goroutine must be greater than 0")
	}
	return &Glimit{
		n: max_goroutine,
		c: make(chan struct{}, max_goroutine),
	}, nil
}

// 在限制内运行f函数
func (g *Glimit) Run(f func() error) {
    wg.Add(1)
	g.c <- struct{}{} // 阻塞直到有空闲槽位
	go func() {

		defer func() {
			if r := recover(); r != nil {
				log.Printf("panic occurred in goroutine with msg : %v", r)
			}
			//log.Println(`通道被释放`)
			<-g.c
			wg.Done()
		}()

		if err := f(); err != nil {
			log.Printf("Function execution failed  with error: %v", err)
		}
	}()
}

var wg = sync.WaitGroup{}

func main() {
	number := 8
	g, err := New_workers(3) // 定义一次最多使用3个并发
	if err != nil {
		log.Fatalf("Failed to initialize Glimit: %v", err)
	}

	for i := 0; i < number; i++ {

		value := i // value只在for循环体里有效
		// 在循环里定义每次要执行的函数
		goFunc := func() error {

			// 做一些业务逻辑处理
			log.Printf(" %v go func: %d \n", time.Now(), value)
			//	time.Sleep(time.Second)
			// 模拟一个可能发生的错误
			if value == 5 {

				return fmt.Errorf("simulated error at value: %d", value)
				//panic(fmt.Errorf("simulated error at value: %d", value))
			}
			return nil
		}
		g.Run(goFunc)
	}
	wg.Wait() // 等待结束
	log.Println("ALL DONE!")

}

  优化后的代码

posted @ 2022-06-27 16:16  wsh3166Sir  阅读(203)  评论(7)    收藏  举报