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

Go 1.16中如何便捷管理不同结构体的并发获取结果

适用于Go 1.16的并发结果收集方案

针对你的场景,推荐用接口+任务封装的方式实现,既保证类型安全,又能充分利用并发特性,还能避免聚合结构体冗余、反射类型转换的问题。

核心思路

  1. 定义一个通用的Result标记接口,作为所有返回结构体的统一类型载体;
  2. 为每个业务类型(Person/Pet)封装对应的任务逻辑,实现统一的执行方法;
  3. 批量启动所有任务的goroutine,将结果统一发送到通道中,最后遍历处理。

具体实现代码

第一步:定义通用接口和任务封装

import "sync"

// Result 标记接口,用于统一所有业务结构体类型
type Result interface{}

// 封装Person查询任务的函数
func wrapPersonQuery(id int) func() Result {
    return func() Result {
        return <-GetPerson(id)
    }
}

// 封装Pet查询任务的函数
func wrapPetQuery(id int) func() Result {
    return func() Result {
        return <-GetPet(id)
    }
}

第二步:并发执行任务并收集结果

func main() {
    // 构造所有需要执行的任务列表
    var taskFuncs []func() Result
    // 添加Person查询任务
    taskFuncs = append(taskFuncs, wrapPersonQuery(1), wrapPersonQuery(2))
    // 添加Pet查询任务
    taskFuncs = append(taskFuncs, wrapPetQuery(3), wrapPetQuery(4))

    // 初始化结果通道和WaitGroup
    resultCh := make(chan Result, len(taskFuncs))
    var wg sync.WaitGroup
    wg.Add(len(taskFuncs))

    // 并发启动所有任务
    for _, fn := range taskFuncs {
        fn := fn // 闭包捕获当前循环变量,避免变量复用问题
        go func() {
            defer wg.Done()
            resultCh <- fn()
        }()
    }

    // 所有任务完成后关闭结果通道
    go func() {
        wg.Wait()
        close(resultCh)
    }()

    // 遍历处理所有结果
    for res := range resultCh {
        switch v := res.(type) {
        case Person:
            // 处理Person类型结果,比如打印或存入统一存储
            println("Person:", v.Name, v.Age)
        case Pet:
            // 处理Pet类型结果
            println("Pet:", v.Name, v.Type)
        }
    }
}

方案优势

  • 类型安全:完全基于编译时检查,避免反射带来的类型转换错误和性能损耗;
  • 并发高效:所有任务同时启动,充分利用Go的goroutine并发能力;
  • 扩展性强:新增业务类型时,只需要添加对应的包装函数即可,无需修改核心收集逻辑;
  • 代码简洁:避免了聚合结构体的参数冗余问题,任务定义清晰。

进阶:面向对象风格的任务封装

如果需要更清晰的任务职责划分,也可以用结构体封装任务:

// PersonTask 封装Person的查询任务
type PersonTask struct {
    ID int
}

// Execute 执行任务并返回结果
func (t PersonTask) Execute() Result {
    return <-GetPerson(t.ID)
}

// PetTask 封装Pet的查询任务
type PetTask struct {
    ID int
}

// Execute 执行任务并返回结果
func (t PetTask) Execute() Result {
    return <-GetPet(t.ID)
}

// 执行逻辑
func main() {
    var tasks []interface {
        Execute() Result
    }
    tasks = append(tasks, PersonTask{ID: 1}, PersonTask{ID: 2})
    tasks = append(tasks, PetTask{ID: 3}, PetTask{ID: 4})

    // 后续并发执行和结果收集逻辑与之前一致,仅遍历对象改为调用task.Execute()
}

这个方案更适合任务带有额外参数或复杂逻辑的场景,代码可读性更强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 18:06:40