管道和消息队列是 go 中用于 goroutine 通信的原语。管道是无缓冲通道,立即传递数据;消息队列是缓冲通道,允许存储多个消息。实战案例 中,管道可用于并行处理任务,如将一组任务发送到管道并使用 goroutine 池并行处理。
Go 中的管道与消息队列
在 Go 中,管道和消息队列是用于 goroutine 之间通信的两个基本原语。
管道
“go语言免费”;
管道是无缓冲的通信通道,数据会立即从写入端传递到读取端。管道通常用于在 goroutine 之间传递小块数据。
创建管道:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
import "fmt"
func main() {
// 创建一个管道
ch := make(chan int)
// 写入数据
ch <- 42
// 读取数据
v := <-ch
fmt.Println(v) // 输出 42
}
消息队列
消息队列是一种缓冲的通信通道,允许在写入端和读取端之间存储多个消息。这使得 goroutine 可以按自己的节奏发送和接收消息,而不必担心丢失或阻塞。
使用内置的 sync.Mutex 和 sync.Cond 创建一个简单的消息队列:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package main
import (
"fmt"
"sync"
"time"
)
func main() {
// 创建一个消息队列
var (
queue = []int{}
mu sync.Mutex
cond sync.Cond
)
// 启动一个生产者 goroutine
go func() {
for {
mu.Lock()
queue = append(queue, 42)
cond.Signal()
mu.Unlock()
time.Sleep(time.Second)
}
}()
// 启动一个消费者 goroutine
go func() {
for {
mu.Lock()
for len(queue) == 0 {
cond.Wait()
}
v := queue[0]
queue = queue[1:]
mu.Unlock()
fmt.Println(v) // 输出 42
}
}()
// 等待 goroutine 退出
time.Sleep(time.Second 5)
}
实战案例 :并行处理任务
管道或消息队列可以用于并行处理任务。以下是一个示例,说明如何使用管道并行处理一组任务:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main
import (
"fmt"
"sync"
)
func main() {
// 定义任务
tasks := []int{1, 2, 3, 4, 5}
// 创建管道
ch := make(chan int)
// 启动 goroutine 池来处理任务
var wg sync.WaitGroup
for i := 0; i < 4; i++ {
wg.Add(1)
go func(ch chan int) {
for task := range ch {
fmt.Println(task)
}
wg.Done()
}(ch)
}
// 将任务发送到管道
for _, task := range tasks {
ch <- task
}
// 关闭管道
close(ch)
// 等待 goroutine 池完成
wg.Wait()
}
以上就是golang并发编程中的管道与消息队列的详细内容,更多请关注其它相关文章!