Go高级并发模式

Go对并发提供了强大的原生支持,本文讨论Go的高级并发模式,理解这些并发模式,可以帮助我们编写高效的Go应用程序。原文: Advanced Concurrency Patterns in Go

"并发不是并行,但使并行成为可能。" ------ Rob Pike

本文将深入探讨Go中的一些高级并发模式。Go以其内置的并发原语而闻名,理解这些模式可以帮助我们编写更高效、可扩展的应用程序。


1. 基础Goroutine

goroutine是由Go运行时管理的轻量级线程。要启动一个goroutine,只需在函数前使用go关键字。

golang 复制代码
package main

import (
 "fmt"
 "time"
)

func sayHello() {
 fmt.Println("Hello from a goroutine!")
}

func main() {
 go sayHello() // This starts a new goroutine.
 time.Sleep(1 * time.Second) // Give goroutine some time to execute.
}

在本例中,sayHello函数与main函数并发运行。


2. Channel和Select

channel用于在程序之间进行通信,同步执行并确保数据安全。

基础channel示例

golang 复制代码
package main

import "fmt"

func main() {
 message := make(chan string) // create a new channel

 go func() { // start a goroutine
  message <- "Hello from the other side!" // send a message to the channel
 }()

 msg := <-message // receive a message from the channel
 fmt.Println(msg)
}

我们可以通过channel安全的在例程之间发送和接收消息。

使用Select

select允许程序等待多个通信操作,它就像一个针对channel的switch语句。

golang 复制代码
package main

import (
 "fmt"
 "time"
)

func main() {
 ch1 := make(chan string)
 ch2 := make(chan string)

 go func() {
  for {
   ch1 <- "from ch1"
   time.Sleep(2 * time.Second)
  }
 }()

 go func() {
  for {
   ch2 <- "from ch2"
   time.Sleep(3 * time.Second)
  }
 }()

 go func() {
  for {
   select {
   case msg1 := <-ch1:
    fmt.Println(msg1)
   case msg2 := <-ch2:
    fmt.Println(msg2)
   }
  }
 }()

 select {} // keep the main function alive
}

基于select,我们可以同时处理多个channel。


3. 高级模式: 工作池(Worker Pool)

工作池是一种限制运行的goroutine数量的方法。

工作池示例

golang 复制代码
package main

import (
 "fmt"
 "time"
)

func worker(id int, jobs <-chan int, results chan<- int) {
 for j := range jobs {
  fmt.Println("worker", id, "processing job", j)
  time.Sleep(time.Second)
  results <- j * 2
 }
}

func main() {
 const numJobs = 5
 jobs := make(chan int, numJobs)
 results := make(chan int, numJobs)

 // start 3 workers
 for w := 1; w <= 3; w++ {
  go worker(w, jobs, results)
 }

 // send jobs
 for j := 1; j <= numJobs; j++ {
  jobs <- j
 }
 close(jobs)

 // collect results
 for a := 1; a <= numJobs; a++ {
  <-results
 }
}

工作池帮助我们管理和限制并发运行的goroutine数量。


结论

Go中的并发(goroutine、channel和模式)为开发人员提供了强大的工具集。通过理解和利用这些概念,可以构建高性能和可伸缩的应用程序。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

本文由mdnice多平台发布

相关推荐
小杨互联网19 小时前
Go 现代 CLI 工具离线镜像合集
开发语言·后端·golang·开源·go·命令行
hourinX1 天前
从直接填格子到筛选图案:头像生成这部分是怎样改过来的—— gdenticon 重构日志(三)
go
我不会起名字3221 天前
Redis 从 0 到 1(十三):分布式锁被误删、锁不住?Go 无 Lua 实现 3 级防御
redis·go·分布式锁·watch·setnx
hourinX2 天前
从 v1 到 v2,我重新拆了头像生成的整条链路—— gdenticon 重构日志(二)
go
FungLeo2 天前
成为全栈·Go 后端篇·分类树与标签关系:目录变更为何需要协调
golang·go·gorm·数据库事务·分类树·成为全栈
FungLeo2 天前
成为全栈·Go 后端篇·文章查询与展示投影:安全分页、排序和软删除
golang·go·gorm·分页查询·成为全栈·sql安全
KevinAshen673 天前
用 Go 修复旧下载工具:从接口 403 到凭证截断的完整复盘
go·github
FungLeo4 天前
成为全栈·Go 后端篇·跨语言认证兼容:Node 与 Go 如何互认 JWT 和密码
golang·go·jwt·身份认证·成为全栈·bcrypt
FungLeo4 天前
成为全栈·Go 后端篇·重写之前先锁基线:契约、Node 版本与行为清单
golang·node.js·go·openapi·契约测试·成为全栈
小满zs4 天前
Go语言第十七章(反射)
后端·go