package main
import (
"fmt"
)
func main() {
reqCh := make(chan request)
respCh := make(chan response)
// 启动 10 个 goroutine 并发写入 map
for i := 0; i < 10; i++ {
go writeMap(reqCh, respCh)
}
// 启动 10 个 goroutine 并发读取 map
for i := 0; i < 10; i++ {
go readMap(reqCh, respCh)
}
// 向请求通道中发送读取和写入请求
for i := 0; i < 20; i++ {
if i%2 == 0 {
reqCh <- request{operation: "write", key: fmt.Sprintf("key%d", i/2), value: i / 2}
} else {
reqCh <- request{operation: "read", key: fmt.Sprintf("key%d", i/2)}
}
}
// 打印接收到的响应
for i := 0; i < 20; i++ {
resp := <-respCh
if resp.err != nil {
fmt.Printf("error: %v\n", resp.err)
} else {
fmt.Printf("key: %s, value: %d\n", resp.key, resp.value)
}
}
}
type request struct {
operation string
key string
value int
}
type response struct {
key string
value int
err error
}
func writeMap(reqCh chan request, respCh chan response) {
m := make(map[string]int)
for req := range reqCh {
if req.operation == "write" {
m[req.key] = req.value
respCh <- response{key: req.key, value: req.value}
} else {
respCh <- response{key: req.key, err: fmt.Errorf("invalid operation: %s", req.operation)}
}
}
}
func readMap(reqCh chan request, respCh chan response) {
m := make(map[string]int)
for req := range reqCh {
if req.operation == "read" {
value, ok := m[req.key]
if ok {
respCh <- response{key: req.key, value: value}
} else {
respCh <- response{key: req.key, err: fmt.Errorf("key not found: %s", req.key)}
}
} else {
respCh <- response{key: req.key, err: fmt.Errorf("invalid operation: %s", req.operation)}
}
}
}
这段代码展示了如何使用goroutine和通道实现并发读写一个map。
首先,我们定义了两个通道 reqCh 和 respCh,用于在读写goroutine之间传递请求和响应。
然后,我们使用两个循环分别启动了10个写入goroutine和10个读取goroutine。每个写入goroutine都会调用 writeMap 函数,而每个读取goroutine都会调用 readMap 函数。
在主函数中,我们使用一个循环向 reqCh 通道发送读取和写入请求。对于偶数次循环,我们发送一个写入请求,其中包含操作类型为 "write",键为格式化后的字符串 "key%d",值为循环索引的一半。对于奇数次循环,我们发送一个读取请求,其中包含操作类型为 "read",键为格式化后的字符串 "key%d"。
然后,我们使用另一个循环从 respCh 通道接收响应,并根据响应的类型进行处理。如果响应中的 err 字段不为空,则打印错误消息。否则,打印键和值。
writeMap 函数和 readMap 函数都是无限循环,通过 range 关键字从 reqCh 通道中接收请求。在 writeMap 函数中,我们创建了一个空的 map,然后根据请求的操作类型进行写入或错误处理,并将响应发送到 respCh 通道。在 readMap 函数中,我们也创建了一个空的 map,然后根据请求的操作类型进行读取或错误处理,并将响应发送到 respCh 通道。
总体来说,这段代码展示了如何使用goroutine和通道实现并发读写一个map,并通过请求和响应通道进行通信。通过并发读写map,可以提高程序的性能和效率。