Golang并发模式之fan-in fan-out应用

fan-out指将任务分发给多个goroutine并发处理,fan-in指将多个结果通道合并为一个。通过输入通道分发URL任务,启动10个worker并发抓取数据,每个worker将响应长度发送到输出通道,主函数从输出通道接收并汇总结果,实现高效并发处理。需注意控制并发数、关闭通道时机及使用context管理超时。

golang并发模式之fan-in fan-out应用

在Go语言中,fan-in fan-out 是一种常见的并发设计模式,用于提升数据处理的吞吐量。它通过多个goroutine并行处理任务(fan-out),再将结果汇聚到一个通道中(fan-in),非常适合需要高并发处理大量独立任务的场景,比如数据抓取、消息处理、批量计算等。

什么是fan-out(扇出)

fan-out 指的是将输入数据分发给多个工作 goroutine 并发处理。这样可以充分利用多核CPU,加快处理速度。

例如:有一批待处理的任务,我们启动多个 worker 同时消费这些任务,每个 worker 独立运行,互不阻塞。

常见做法:

立即学习“go语言免费学习笔记(深入)”;

使用一个输入通道分发任务启动多个 goroutine 从该通道读取并处理每个 worker 处理完后将结果发送到输出通道

什么是fan-in(扇入)

fan-in 是把多个通道的数据合并到一个通道中,方便主流程统一接收和处理所有 worker 的输出。

利用 Go 的通道选择机制(select),可以从多个输出通道中读取数据,无需等待某个特定通道。

实现方式通常有两种:

显式使用 select 监听多个通道通过独立的 goroutine 将各个 worker 的输出写入同一个结果通道

一个完整的fan-in fan-out示例

假设我们要处理一批URL,获取它们的响应长度,并统计总耗时。我们可以用 fan-out 启动多个 worker 并发请求,再用 fan-in 收集结果。

func fetch(url string) int {    resp, err := http.Get(url)    if err != nil {        return 0    }    defer resp.Body.Close()    body, _ := io.ReadAll(resp.Body)    return len(body)}

func main() {urls := []string{ / 一堆URL / }

// 输入通道in := make(chan string, len(urls))for _, url := range urls {    in <- url}close(in)// 输出通道out := make(chan int, len(urls))// 启动多个worker(fan-out)for i := 0; i < 10; i++ {    go func() {        for url := range in {            length := fetch(url)            out <- length        }    }()}// 关闭out通道,当所有worker完成时go func() {    for i := 0; i < 10; i++ {        <-inWorkerDone // 等待所有worker退出(简化起见可省略计数)    }    close(out)}()// 读取所有结果(fan-in)var total intfor result := range out {    total += result}fmt.Println("Total data length:", total)

}

这个例子中:

in 通道作为任务队列,被多个 worker 共享消费每个 worker 处理完任务后把结果发到 out 通道主函数从 out 中接收所有结果,完成汇聚

适用场景与注意事项

fan-in fan-out 特别适合以下情况:

任务之间无依赖,可独立处理I/O密集型操作,如网络请求、文件读写需要控制并发度,避免资源耗尽

需要注意的地方:

合理设置 worker 数量,避免系统过载确保所有 sender 都关闭通道后再从接收端退出,防止 panic使用 context 控制超时或取消,增强健壮性结果通道最好带缓冲,或配合 WaitGroup 使用,避免goroutine泄漏

基本上就这些。掌握 fan-in fan-out 模式,能让你写出更高效、清晰的并发程序。关键是理解“分发 + 聚合”的思想,再结合Go的通道和goroutine轻松实现。

以上就是Golang并发模式之fan-in fan-out应用的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1406155.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月15日 22:00:46
下一篇 2025年12月15日 22:01:03

相关推荐

  • Go语言:使用unsafe包将单变量指针转换为切片

    Go语言中的切片不仅包含指向底层数组的指针,还包括长度和容量信息,这与C语言的纯指针概念不同。因此,不能直接将单个变量的指针作为切片使用。本文将探讨Go切片的基本结构,解释为何直接创建切片无法满足内存共享需求,并演示如何利用unsafe包将单个变量的指针转换为指向其内存的切片,同时强调使用unsaf…

    好文分享 2025年12月15日
    000
  • GolangWeb API分页与查询参数处理实践

    Golang Web API分页与查询参数处理需解析Query String并转为结构体,使用gorilla/schema绑定参数,结合validator库验证,通过offset和limit实现分页,支持时间范围、多值查询,优化建议包括索引、游标分页、缓存及避免N+1查询。 直接来说,Golang …

    2025年12月15日
    000
  • Go语言中的尾调用优化:深入解析与实践

    Go语言目前不提供语言层面的尾调用优化(TCO)保证,尽管在特定编译器(如旧版6g/8g和gccgo)的某些有限场景下可能存在。Go官方不计划强制所有编译器实现TCO,并建议开发者通过使用循环或goto语句来替代尾递归,以避免栈溢出并提升性能。本文将详细探讨Go对TCO的态度、原因及推荐的替代方案。…

    2025年12月15日
    000
  • Go语言中如何将单个值作为切片处理:理解与unsafe实践

    在Go语言中,将单个变量(如uint8)转换为切片,以满足io.Reader.Read等函数对切片参数的要求,是一个常见的疑问。本文将深入探讨Go切片与C语言数组指针的本质区别,解释为何直接传递变量地址不可行。随后,详细介绍使用unsafe包实现此转换的方法,并提供实际代码示例。最后,强调unsaf…

    2025年12月15日
    000
  • Golang使用testing包结合第三方库测试

    Go语言测试常用testing包结合第三方库提升效率。1. 使用testify/assert简化断言,如assert.Equal替代if判断,提升可读性;2. 用gomock生成接口mock,模拟数据库或HTTP调用,避免真实依赖;3. 采用go-cmp的cmp.Diff进行精细结构比较,支持忽略时…

    2025年12月15日
    000
  • Go Map迭代顺序:理解与实现有序访问

    Go语言中的Map是一种无序的数据结构,其迭代顺序不确定且非稳定。本文将深入探讨Go Map迭代无序的原因,并提供两种实现有序访问的方法:一是利用切片或数组进行直接索引(适用于键为连续整数的特定场景),二是通用且推荐的通过排序键切片来间接实现Map的有序遍历。 Go Map的无序性:深入理解 go语…

    2025年12月15日
    000
  • Go语言中HTTP服务器设置Cookie的实践指南

    本文旨在指导开发者如何在Go语言的net/http包中正确地通过HTTP服务器设置Cookie。核心在于理解Cookie应通过http.ResponseWriter进行设置,而非http.Request。我们将详细介绍http.SetCookie函数的使用方法,并通过代码示例演示如何构建和发送Coo…

    2025年12月15日
    000
  • Go语言二叉搜索树遍历:深度解析排序特性与并发实践

    深入探讨Go语言中二叉搜索树的遍历机制,重点分析不同遍历顺序(如中序遍历)如何影响输出序列的排序特性。文章将结合Go并发通道,阐述在比较两棵树是否包含相同值时,遍历顺序的关键作用,并提供实用的代码示例与专业指导。 二叉搜索树(BST)的特性 在深入探讨遍历方法之前,理解二叉搜索树(binary se…

    2025年12月15日
    000
  • Python与Ruby中协程和续体在Web编程中的应用与演变

    本文探讨了Python协程和Ruby续体在Web编程中用于状态管理的潜力及其未被广泛采纳的原因。尽管它们曾被视为优雅的解决方案,能简化跨请求状态维护,但随着AJAX等异步技术兴起,Web应用范式转向事件驱动,使得传统意义上的续体和协程在处理高层级多请求流程上的优势减弱。当前,协程更多应用于异步I/O…

    2025年12月15日
    000
  • Golang指针与接口断言使用实例

    指针用于直接操作内存地址上的数据,接口断言则实现类型安全转换。当接口存储指针时,断言需使用对应指针类型,如 animal.(*Dog),否则会失败。结合指针与接口断言可在切片遍历中通过类型开关(type switch)精准识别并处理 *Dog、string 等多种类型,提升代码灵活性和效率。 在Go…

    2025年12月15日
    000
  • Go语言中从单一变量创建切片以满足io.Reader接口要求

    本文探讨了在Go语言中如何将单一变量转换为切片以满足如io.Reader.Read等需要切片参数的接口。我们首先解释了Go切片与C语言指针的区别,接着介绍了两种创建切片的方法:一种是直接创建包含变量值的切片(涉及值拷贝),另一种是使用unsafe包实现与变量共享内存的切片。最后,针对io.Reade…

    2025年12月15日
    000
  • Go 语言中 Map 合并的实践与考量

    本文探讨了 Go 语言中合并两个 Map(映射)的最佳实践。Go 标准库并未提供类似 PHP array_merge 的内置函数,因此推荐使用简洁的循环遍历方式实现键值对的合并。文章将详细介绍这种直观方法,并讨论自定义合并函数在有无泛型情况下的应用,旨在帮助开发者高效、清晰地处理 Map 合并需求。…

    2025年12月15日
    000
  • Go语言中的尾调用优化

    Go语言,作为一门现代化的编程语言,在性能优化方面一直备受关注。其中,尾调用优化(Tail Call Optimization, TCO)是函数式编程中一项重要的优化技术,它可以避免递归调用时栈溢出的问题,并提升程序性能。那么,Go语言是否支持尾调用优化呢? 正如前文所述,Go语言在尾调用优化方面的…

    2025年12月15日
    000
  • Go语言二叉树遍历与并发比较深度解析

    本文深入探讨Go语言中二叉树的遍历与比较机制,重点解析golang.org/x/tour/tree包中二叉搜索树的特性。通过分析Walk函数在不同遍历顺序下的行为,以及Same函数如何利用并发和通道进行树比较,揭示了遍历顺序对输出结果的关键影响,并强调了二叉搜索树的有序性在实现特定功能(如排序)中的…

    2025年12月15日
    000
  • Golangslice遍历优化与CPU缓存利用

    Go中优化slice遍历需提升缓存命中率:优先使用索引for循环避免range复制,合理排列struct字段减少内存对齐浪费,并采用循环分块处理大slice以增强数据局部性。 在Go语言中,slice 是最常用的数据结构之一。当处理大规模数据时,遍历 slice 的性能会显著受到 CPU 缓存命中率…

    2025年12月15日
    000
  • Go语言中合并Map的实用指南

    本文探讨了在Go语言中合并两个Map的最佳实践。鉴于Go标准库中没有直接的array_merge或map_merge函数,教程将重点介绍如何使用简洁的循环结构进行Map合并,并讨论了创建通用合并函数的局限性及其类型安全性考虑,同时引入了Go泛型在现代Go版本中的应用。 在go语言的日常开发中,我们经…

    2025年12月15日
    000
  • Golang环境搭建常见问题排查技巧

    配置PATH和GOROOT避免版本冲突,确保go命令可用;2. 国内设置GOPROXY代理解决模块下载失败;3. 使用build标签时需指定对应tag,确保main包存在以完成构建。 搭建Golang开发环境时,新手常会遇到各种问题。核心在于理解Go的模块机制和环境变量作用。定位问题要从报错信息入手…

    2025年12月15日
    000
  • Go语言中Map迭代顺序不确定性及如何实现有序遍历

    Go语言的map类型在迭代时并不保证元素的顺序,这是其设计特性,旨在优化性能而非提供固定顺序。若需按特定顺序遍历map,常见且推荐的方法是提取map的所有键到一个切片中,对该切片进行排序,然后依据排序后的键来逐一访问map中的值,从而实现有序遍历。 Go Map迭代的无序性解析 go语言中的map(…

    2025年12月15日
    000
  • Go 语言跨平台编译实战:简化流程与环境配置

    Go 1.5 版本极大简化了跨平台编译流程,开发者无需复杂配置或外部工具,只需通过设置 GOOS 和 GOARCH 环境变量,即可轻松为不同操作系统和架构生成可执行文件。本文将详细介绍这一内置机制,并提供实用的命令行示例,帮助您高效完成 Go 应用的跨平台构建。 Go 早期版本的跨平台编译挑战 在 …

    2025年12月15日
    000
  • Golang容器日志收集与集中监控示例

    Golang容器日志应通过结构化输出至标准流实现高效收集。首先在应用层使用zap或logrus等库生成JSON格式日志,并输出到stdout/stderr;接着在Kubernetes中部署Filebeat或Fluent Bit作为DaemonSet,采集各节点容器日志并转发至ELK或Loki等集中式…

    2025年12月15日
    000

发表回复

登录后才能评论
关注微信