当前位置: 首页 > news >正文

Go09-并发编程

第8章:并发编程

8.1 并发基础

Go 使用 goroutine 和 channel 实现并发,这是 Go 最强大的特性之一。

Goroutine

Goroutine 是轻量级线程,由 Go 运行时管理:

packagemainimport("fmt""time")funcsayHello(namestring){fori:=0;i<5;i++{fmt.Printf("Hello, %s! (%d)\n",name,i)time.Sleep(100*time.Millisecond)}}funcmain(){// 启动 goroutinegosayHello("张三")gosayHello("李四")// 主 goroutine 等待time.Sleep(1*time.Second)fmt.Println("主程序结束")}

启动多个 Goroutine

funcmain(){// 启动多个 goroutinefori:=0;i<10;i++{gofunc(nint){fmt.Printf("goroutine %d\n",n)}(i)// 注意:传递参数避免闭包问题}time.Sleep(time.Second)}

8.2 Channel

Channel 是 goroutine 之间通信的管道。

基本 Channel

// 创建 channelch:=make(chanint)// 发送数据gofunc(){ch<-42// 发送}()// 接收数据value:=<-ch// 接收fmt.Println(value)// 42// 关闭 channelclose(ch)

带缓冲的 Channel

// 无缓冲 channel(同步)ch1:=make(chanint)// 带缓冲 channel(异步)ch2:=make(chanint,10)// 缓冲区大小为 10// 发送数据(不阻塞,直到缓冲区满)ch2<-1ch2<-2// 接收数据fmt.Println(<-ch2)// 1fmt.Println(<-ch2)// 2

Channel 方向

// 只发送 channelfuncproducer(chchan<-int){fori:=0;i<10;i++{ch<-i}close(ch)}// 只接收 channelfuncconsumer(ch<-chanint){forv:=rangech{fmt.Println(v)}}funcmain(){ch:=make(chanint)goproducer(ch)consumer(ch)}

8.3 Channel 操作

Select 语句

// 同时监听多个 channelfuncmain(){ch1:=make(chanstring)ch2:=make(chanstring)gofunc(){time.Sleep(1*time.Second)ch1<-"来自 channel 1"}()gofunc(){time.Sleep(2*time.Second)ch2<-"来自 channel 2"}()// select 等待第一个完成的 channelselect{casemsg:=<-ch1:fmt.Println(msg)casemsg:=<-ch2:fmt.Println(msg)case<-time.After(3*time.Second):fmt.Println("超时")}}

超时控制

funcfetchData()(string,error){ch:=make(chanstring,1)gofunc(){// 模拟耗时操作time.Sleep(2*time.Second)ch<-"数据"}()select{caseresult:=<-ch:returnresult,nilcase<-time.After(1*time.Second):return"",errors.New("请求超时")}}

非阻塞操作

select{casemsg:=<-ch:fmt.Println("收到消息:",msg)default:fmt.Println("没有消息")}

8.4 同步原语

sync.WaitGroup

packagemainimport("fmt""sync")funcmain(){varwg sync.WaitGroupfori:=0;i<10;i++{wg.Add(1)// 增加计数器gofunc(nint){deferwg.Done()// 减少计数器fmt.Printf("goroutine %d\n",n)}(i)}wg.Wait()// 等待所有 goroutine 完成fmt.Println("所有 goroutine 完成")}

sync.Mutex

packagemainimport("fmt""sync")typeCounterstruct{mu sync.Mutex valueint}func(c*Counter)Increment(){c.mu.Lock()// 加锁deferc.mu.Unlock()// 解锁c.value++}func(c*Counter)Value()int{c.mu.Lock()deferc.mu.Unlock()returnc.value}funcmain(){counter:=&Counter{}varwg sync.WaitGroupfori:=0;i<1000;i++{wg.Add(1)gofunc(){deferwg.Done()counter.Increment()}()}wg.Wait()fmt.Println("最终值:",counter.Value())// 1000}

sync.RWMutex(读写锁)

typeCachestruct{mu sync.RWMutex itemsmap[string]string}func(c*Cache)Get(keystring)(string,bool){c.mu.RLock()// 读锁deferc.mu.RUnlock()value,ok:=c.items[key]returnvalue,ok}func(c*Cache)Set(key,valuestring){c.mu.Lock()// 写锁deferc.mu.Unlock()c.items[key]=value}

sync.Once

typeSingletonstruct{instanceinterface{}once sync.Once}func(s*Singleton)Get()interface{}{s.once.Do(func(){s.instance=createInstance()})returns.instance}

sync.Map

packagemainimport("fmt""sync")funcmain(){varm sync.Map// 存储m.Store("key1","value1")m.Store("key2","value2")// 读取ifvalue,ok:=m.Load("key1");ok{fmt.Println(value)}// 遍历m.Range(func(key,valueinterface{})bool{fmt.Printf("%v: %v\n",key,value)returntrue// 返回 false 停止遍历})}

8.5 并发模式

Worker Pool

funcworker(idint,jobs<-chanint,resultschan<-int){forjob:=rangejobs{fmt.Printf("worker %d 处理 job %d\n",id,job)time.Sleep(time.Second)results<-job*2}}funcmain(){jobs:=make(chanint,100)results:=make(chanint,100)// 启动 workersforw:=1;w<=3;w++{goworker(w,jobs,results)}// 发送 jobsforj:=1;j<=9;j++{jobs<-j}close(jobs)// 收集结果fora:=1;a<=9;a++{fmt.Println("结果:",<-results)}}

Fan-out / Fan-in

// Fan-out: 多个 worker 读取同一个 channel// Fan-in: 多个 worker 写入同一个 channelfuncfanOut(input<-chanint,workersint)[]<-chanint{channels:=make([]<-chanint,workers)fori:=0;i<workers;i++{channels[i]=process(input)}returnchannels}funcfanIn(channels...<-chanint)<-chanint{varwg sync.WaitGroup merged:=make(chanint)for_,ch:=rangechannels{wg.Add(1)gofunc(c<-chanint){deferwg.Done()forv:=rangec{merged<-v}}(ch)}gofunc(){wg.Wait()close(merged)}()returnmerged}

Pipeline

funcgenerate(nums...int)<-chanint{out:=make(chanint)gofunc(){for_,n:=rangenums{out<-n}close(out)}()returnout}funcsquare(in<-chanint)<-chanint{out:=make(chanint)gofunc(){forn:=rangein{out<-n*n}close(out)}()returnout}funcmain(){// Pipeline: generate -> squareforv:=rangesquare(generate(1,2,3,4,5)){fmt.Println(v)// 1, 4, 9, 16, 25}}

8.6 练习

  1. 实现一个简单的并发爬虫
  2. 使用 Worker Pool 模式处理批量任务
  3. 实现一个并发安全的缓存
  4. 编写一个 Pipeline 处理数据流

8.7 下一章

下一章我们将学习 Go 语言的标准库精讲。

http://www.jsqmd.com/news/1202503/

相关文章:

  • 2026年AI Agent市场从百花齐放到分层定局,选型逻辑变了:企业级智能体落地全景深度解析
  • 2026化工行业 GHS/CLP 国产标签打印软件合规打印方案
  • 搞大事掀桌子,万套授权免费送, AIGC工具迎来平权新选择!
  • Claude Code对接DeepSeek本地部署全链路指南
  • Linux服务器双向SSH免密登录配置与安全实践指南
  • atom-script的未来发展:路线图与功能规划展望
  • 如何提前规避高校 AI 审查?实测有效 AIGC 检测降重工具盘点
  • Pandas数据分析从入门到实战:58个核心知识点全面掌握
  • 公共阻抗耦合原理与电子系统抗干扰设计
  • Lovable氛围编程:语义知识图谱驱动的开发操作系统
  • CANN/asc-devkit SIMD乘加函数
  • go10-标准库精讲
  • 论文落地的数据鸿沟:训练集、评测集与生产数据的分布偏差校准实践
  • 轻量化 MES 助力中小制造转型 —— 励拓云 MES 背景介绍
  • Typora画图进阶(1)-- 用Mermaid flowchart重构复杂流程图
  • 低延迟与高音质兼得:Real-time RE-USE质量-延迟权衡策略详解
  • CAN总线共模干扰解决方案与共模电感选型指南
  • VSCode插件AI对话链路深度解析:状态机+流式解析架构
  • 开关电源质量检测9大核心项目与工程实践
  • 电源工程师必备:GS波形分析与实战诊断
  • 2026快速建团队,美国员工外包服务商推荐 - 2027品牌AI展
  • 免费高效的Unity开发工具:SuperScience全部功能清单与使用技巧
  • 如何为FightClub5eXML贡献内容:社区驱动的DD 5e资源库
  • AI内容泛滥:社交媒体25%长文由AI生成,LinkedIn成重灾区
  • Windows系统鼠标指针自定义安装与故障排查指南
  • OpenAI Codex提示词工作流:九套实战方案提升AI编程效率
  • 小程序字体图标实战:优势、配置与性能优化
  • Grape-Entity 测试策略:如何高效测试你的 API 实体层
  • 2026 佛山意式极简家具工厂推荐|5 家大宅专用源头厂深度测评榜单 - siouxx
  • CANN/Ascend C数据搬运API