最近实训的后端课作业要求用Go语言写一个扫描文件然后并发计算MD5值,算是对Go语言基本使用的一个小demo,主要是包括了文件扫描,并发和计算MD5这三部分,虽然没学过Go语言,不过Go最大的优势就是简单,如果有其他编程语言的基础的话,语法方面看一看文档上手很快。
文件扫描
首先是文件扫描,这里使用的是递归扫描的方法,因为文件夹之中一般还会嵌套有文件夹,需要递归扫描直到扫描的路径是一个文件而不是一个文件夹, getAllFileName
函数最终返回的是一个包含输入路径下的所有文件绝对路径的数组
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
| func getAllFileName(pathName string) ([]string, error) { result := []string{}
fis, err := ioutil.ReadDir(pathName) if err != nil { return result, err }
for _, fi := range fis { fullname := pathName + "/" + fi.Name() if fi.IsDir() { temp, err := getAllFileName(fullname) if err != nil { fmt.Println(err) } else { result = append(result, temp...) } } else { _, err := os.ReadFile(fullname) if err != nil { fmt.Println(err) } else { result = append(result, fullname) } } } return result, nil }
|
计算MD5
得到所有文件的绝对路径后就可以去计算MD5的值了,计算MD5的方式很简单,可以参考这篇文章
1 2 3 4 5 6 7 8 9 10 11
| func getMD5(fileName string, isParallel bool) { file, _ := os.ReadFile(fileName) sum := md5.Sum(file) hex.EncodeToString(sum[:])
if isParallel { defer wg.Done() } }
|
Go的并发
main函数中我们分别使用并行和串行来计算相同路径下文件的MD5值,并行计算使用WaitGroup来确保并行计算结果全部返回方便计算时间。
官方文档对 WaitGroup 的描述是:一个 WaitGroup 对象可以等待一组协程结束。
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
| func main() { var pathName string flag.StringVar(&pathName, "p", "", "pathName") flag.Parse()
fileName, err := getAllFileName(pathName) if err != nil { fmt.Println(err) return } length := len(fileName)
begin := time.Now() wg.Add(length) for i := 0; i < length; i++ { go getMD5(fileName[i], true) } wg.Wait() parallel := time.Since(begin).Seconds()
begin = time.Now() for i := 0; i < length; i++ { getMD5(fileName[i], false) } serial := time.Since(begin).Seconds()
fmt.Println("parallel time: ", parallel) fmt.Println("serial time: ", serial) }
|
测试结果
我们简单的扫描一下一个300M的项目,查看打印结果
1 2 3
| go run main.go -p 'project name' parallel time: 1.1069734 serial time: 3.8719537
|
可以看出并行计算还是快很多的。