You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言不使用wg.Wait()实现并发goroutine提前退出与完成检测

优化实现方案

你现有代码的核心逻辑是正确的,但存在一个明显缺陷:带default分支的select会让循环陷入无意义的忙等,持续占用CPU资源,以下是更符合Go语言惯用法的优雅实现:

核心优化点

  • 移除忙等逻辑:去掉select的default分支,让select阻塞等待事件触发,避免空转消耗资源
  • 简化计数逻辑:每次收到成功返回的false结果就累加计数,累计到3时直接返回即可,不需要额外的轮询判断
  • 无goroutine泄露风险:现有代码中channel已经设置了3个缓冲,即使提前返回,剩余goroutine写channel也不会阻塞,不会发生泄露;如果子函数支持中断,还可以额外传入context.Context在提前返回时终止剩余goroutine的执行,避免无用计算

优化后代码示例

package main

import (
	"errors"
	"fmt"
	"time"
)

type checkResult struct {
	isPrimary bool
	err       error
}

func main() {
	x := "something"
	res, err := IsAPrimaryColour(x)

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Printf("Result: %v\n", res)
}

func IsAPrimaryColour(value interface{}) (bool, error) {
	resChan := make(chan checkResult, 3)
	start := time.Now()

	// 合并重复的启动逻辑,不需要重复写三次匿名函数
	checkFuncs := []func(interface{}) (bool, error){IsRed, IsGreen, IsBlue}
	for _, f := range checkFuncs {
		go func(check func(interface{}) (bool, error)) {
			isOk, err := check(value)
			resChan <- checkResult{isPrimary: isOk, err: err}
			fmt.Printf("%T done in %v\n", check, time.Since(start))
		}(f)
	}

	received := 0
	for received < 3 {
		select {
		case res := <-resChan:
			received++
			if res.err != nil {
				fmt.Println("收到错误,直接返回")
				return false, res.err
			}
			if res.isPrimary {
				fmt.Println("收到true结果,直接返回")
				return true, nil
			}
		}
	}
	// 三个校验函数都返回false
	fmt.Println("所有校验都返回false")
	return false, nil
}

func IsRed(value interface{}) (bool, error) {
	return false, nil
}

func IsGreen(value interface{}) (bool, error) {
	time.Sleep(time.Millisecond * 100)
	return true, nil
}

func IsBlue(value interface{}) (bool, error) {
	time.Sleep(time.Millisecond * 200)
	return false, errors.New("something went wrong")
}

内容的提问来源于stack exchange,提问作者user15558657

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 08:57:03