环境
1
2
|
go version go1.16.4 windows/amd64 Intel(R) Core(TM) i7-7820HK CPU @ 2.90GHz 4核心8线程 |
项目需求
处理数个约5MB的小文件
从源目录读取文件并拷贝到目标目录
计算源文件MD5和目标文件MD5进行对比,如不相同则报错并终止程序执行
mapReduce使用说明
1
|
go get -u github.com /tal-tech/go-zero |
需求实现
判断上下文是否中止 → 读取数据 → 写入数据 → 校验MD5
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
|
func fnBuilder(name string ) func () error { return func () error { // 判断上下文是否终止 select { case <-ctx.Done(): return ctx.Err() default : } // 读取源数据 data, _err := os.ReadFile(filepath.Join(sourcePath, fileName)) // 计算源数据MD5 sourceMD5 := hash.Md5(data) // 获取名称 fields := strings.Split(d.Name(), "-" ) // 目标文件路径 distFilePath := filepath.Join(distPath, fileName) // 拷贝数据 os.WriteFile(distFilePath, data, 0600 ) // 校验数据 distData, _err := os.ReadFile(distFilePath) distMD5 := hash.Md5(distData) if !bytes.EqualFold(sourceMD5, distMD5) { return errors. New ( "md5校验失败" ) } return nil } } |
业务逻辑
创建任务队列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
type SourceMap = map [ string ]fs.DirEntry func CopyFileToDist(ctx context.Context, source SourceMap) (err error ) { // 创建工作队列 work := make ([] func () error , 0 , len (source)) for _name := range source { // 创建任务 work = append (work, fnBuilder(_name)) } switch concurrency { default : // mapReduce case 1 : // sync.waitGroup case 2 : // 串行 } } |
执行方式1:MapReduce
1
2
3
4
5
|
func () { if err = mr.Finish(work...); err != nil { return err } } |
执行方式2:sync.WaitGroup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
func () { var wg sync.WaitGroup wg.Add( len (work)) for k := range work { go func (index int ) { defer wg.Done() if err = work[index](); err != nil { log.Errorln(err) return } }(k) } wg.Wait() } |
执行方式3:串行
1
2
3
4
5
6
7
|
func () { for _, fn := range work { if err = fn(); err != nil { return err } } } |
运行结果
MapReduce
耗时 109220900 ns
1
2
|
{ "file" : "D:/go/src/filenamesSorter/main.go:44" , "func" : "main.init.0" , "level" : "info" , "msg" : "并发处理(0-mapReduce 1-Sync.WaitGroup 2-不并发) 0" , "time" : "2021-06-02T13:32:05+08:00" } { "file" : "D:/go/src/filenamesSorter/main.go:69" , "func" : "main.main" , "level" : "info" , "msg" : "文件分类完毕" , "time" : "2021-06-02T13:32:05+08:00" , "文件数" :17, "耗时(ns)" :109220900} |
sync.WaitGroup
耗时 109798000 ns
1
2
|
{ "file" : "D:/go/src/filenamesSorter/main.go:44" , "func" : "main.init.0" , "level" : "info" , "msg" : "并发处理(0-mapReduce 1-Sync.WaitGroup 2-不并发) 1" , "time" : "2021-06-02T13:31:28+08:00" } { "file" : "D:/go/src/filenamesSorter/main.go:69" , "func" : "main.main" , "level" : "info" , "msg" : "文件分类完毕" , "time" : "2021-06-02T13:31:28+08:00" , "文件数" :17, "耗时(ns)" :109798000} |
串行
耗时 359307700 ns
1
2
|
{ "file" : "D:/go/src/filenamesSorter/main.go:44" , "func" : "main.init.0" , "level" : "info" , "msg" : "并发处理(0-mapReduce 1-Sync.WaitGroup 2-不并发) 2" , "time" : "2021-06-02T13:33:02+08:00" } { "file" : "D:/go/src/filenamesSorter/main.go:69" , "func" : "main.main" , "level" : "info" , "msg" : "文件分类完毕" , "time" : "2021-06-02T13:33:02+08:00" , "文件数" :17, "耗时(ns)" :359307700} |
结论
- 在不严格的情况下,执行效率方面可以认为 mapReduce ≈ sync.WaitGroup
- 易用性(包括并发和错误处理),mapReduce 完胜 sync.WaitGroup
- mapReduce好用
引申阅读
以上就是Golang编程并发工具库MapReduce使用实践的详细内容,更多关于Golang并发工具库MapReduce的资料请关注服务器之家其它相关文章!
原文链接:https://blog.csdn.net/yes169yes123/article/details/117467920