【Go语言快速上手】第二部分:Go语言进阶之并发编程
- 创业
- 2025-08-26 12:03:02

文章目录 一、并发编程1. goroutine:创建和调度 goroutine2. channel:无缓冲 channel、有缓冲 channel、select 语句2.1 无缓冲 channel2.2 有缓冲 channel2.3 select 语句 3. sync 包:Mutex、RWMutex、WaitGroup 等同步原语3.1 Mutex:互斥锁3.2 RWMutex:读写互斥锁3.3 WaitGroup:等待多个 goroutine 完成 一、并发编程
Go 语言的并发编程是其一大亮点。通过 goroutine 和 channel,Go 使得并发编程变得简洁且高效。Go 还提供了 sync 包,包含了多种同步原语,帮助开发者在并发程序中处理共享数据和同步问题。
1. goroutine:创建和调度 goroutinegoroutine 是 Go 中最基本的并发单元,可以认为是轻量级的线程。通过 go 关键字可以轻松创建一个新的 goroutine,并发执行指定的函数或方法。
package main import ( "fmt" "time" ) // 一个简单的并发任务 func sayHello() { time.Sleep(1 * time.Second) fmt.Println("Hello from goroutine!") } func main() { go sayHello() // 创建一个 goroutine fmt.Println("Hello from main!") time.Sleep(2 * time.Second) // 等待 goroutine 执行完毕 }在这个示例中,go sayHello() 启动了一个新的 goroutine,并发执行 sayHello 函数。主函数继续执行并打印输出,最后通过 time.Sleep 等待 goroutine 完成。
2. channel:无缓冲 channel、有缓冲 channel、select 语句
channel 是 Go 语言用于不同 goroutine 之间通信的机制。通过 channel,可以安全地传递数据,避免了数据竞争问题。Go 提供了无缓冲和有缓冲的 channel,以及 select 语句来处理多个 channel 的操作。
2.1 无缓冲 channel无缓冲 channel 会在发送数据和接收数据时进行同步,确保发送和接收操作相互配合。
package main import "fmt" func main() { ch := make(chan string) // 创建一个无缓冲 channel // 启动 goroutine 发送数据 go func() { ch <- "Hello from goroutine!" // 向 channel 发送数据 }() // 接收数据 msg := <-ch fmt.Println(msg) // 输出: Hello from goroutine! } 2.2 有缓冲 channel有缓冲的 channel 可以在发送数据时不必立即等待接收方,直到缓冲区满或接收方取走数据。创建有缓冲 channel 时,可以指定缓冲区的大小。
package main import "fmt" func main() { ch := make(chan string, 2) // 创建一个缓冲区大小为 2 的 channel ch <- "Hello" ch <- "World" // 向 channel 发送两个消息 fmt.Println(<-ch) fmt.Println(<-ch) }在这个示例中,channel 的缓冲区大小为 2,可以在不立即接收的情况下向 channel 发送两个数据。
2.3 select 语句select 语句允许你等待多个 channel 操作。它类似于 switch 语句,但用于处理多个 channel 的发送或接收。
package main import ( "fmt" "time" ) func main() { ch1 := make(chan string) ch2 := make(chan string) go func() { time.Sleep(1 * time.Second) ch1 <- "Message from ch1" }() go func() { time.Sleep(2 * time.Second) ch2 <- "Message from ch2" }() // 使用 select 语句监听多个 channel select { case msg1 := <-ch1: fmt.Println("Received:", msg1) case msg2 := <-ch2: fmt.Println("Received:", msg2) } }在这个示例中,select 会等待 ch1 或 ch2 中的任一 channel 可用。当第一个 channel 可用时,它会立即执行对应的 case,并停止等待。
3. sync 包:Mutex、RWMutex、WaitGroup 等同步原语
Go 提供了 sync 包中的多种同步原语,用于处理并发程序中的共享资源访问问题。
3.1 Mutex:互斥锁Mutex 是最常用的同步原语,它确保同一时刻只有一个 goroutine 可以访问共享资源。通过 Lock 和 Unlock 方法来加锁和解锁。
package main import ( "fmt" "sync" ) var counter int var mutex sync.Mutex func increment() { mutex.Lock() // 加锁 counter++ mutex.Unlock() // 解锁 } func main() { var wg sync.WaitGroup // 启动多个 goroutine 进行并发操作 for i := 0; i < 1000; i++ { wg.Add(1) go func() { defer wg.Done() increment() }() } wg.Wait() // 等待所有 goroutine 执行完毕 fmt.Println("Final counter:", counter) }在这个示例中,使用 Mutex 来保证对 counter 的并发访问是安全的。
3.2 RWMutex:读写互斥锁RWMutex 是一种读写互斥锁,它允许多个 goroutine 同时读取共享资源,但在写操作时会阻止其他的读写操作。
package main import ( "fmt" "sync" ) var counter int var rwMutex sync.RWMutex func read() int { rwMutex.RLock() // 读锁 defer rwMutex.RUnlock() return counter } func write() { rwMutex.Lock() // 写锁 counter++ rwMutex.Unlock() } func main() { var wg sync.WaitGroup // 启动多个 goroutine 进行读写操作 for i := 0; i < 1000; i++ { wg.Add(1) go func() { defer wg.Done() write() }() } for i := 0; i < 1000; i++ { wg.Add(1) go func() { defer wg.Done() read() }() } wg.Wait() fmt.Println("Final counter:", counter) }在这个示例中,RWMutex 允许多个 goroutine 同时进行读操作,但在执行写操作时会锁住资源。
3.3 WaitGroup:等待多个 goroutine 完成WaitGroup 用于等待一组 goroutine 执行完毕。它提供了 Add、Done 和 Wait 方法来控制并发流程。
package main import ( "fmt" "sync" ) func task(wg *sync.WaitGroup) { defer wg.Done() // 执行完毕时调用 Done fmt.Println("Task completed") } func main() { var wg sync.WaitGroup // 启动多个 goroutine for i := 0; i < 5; i++ { wg.Add(1) // 增加等待的 goroutine 数量 go task(&wg) } wg.Wait() // 等待所有 goroutine 执行完毕 fmt.Println("All tasks completed") }在这个示例中,WaitGroup 用于等待多个并发任务完成。
【Go语言快速上手】第二部分:Go语言进阶之并发编程由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【Go语言快速上手】第二部分:Go语言进阶之并发编程”