案例需求:我们的监测系统会定期的检查配置文件的变动,这些配置文件放置在一个独立的文件夹下面,我们可以通过对于整个的文件夹内所有文件进行md5的计算来完成监测,本文就通过Go语言实现了一个命令行工具,完成上述的需求。
1. 单一文件的md5计算
我们首先将需求任务进行分解,既然需要计算文件夹下的所有文件md5值,我们必须先考虑如何实现单一文件的md5值计算。
下面就是一个简单的md5求值程序,这里我们通过参数传递进去需要计算的文件,然后调用go语言提供的内置的crypto包中的函数来完成取值,计算得出的结果使用16进制的方式打印出来。
package main
import (
"crypto/md5"
"fmt"
"io/ioutil"
"os"
)
func Md5SumFile(file string) (value [md5.Size]byte, err error) {
data, err := ioutil.ReadFile(file)
if err != nil {
return
}
value = md5.Sum(data)
return
}
func main() {
if len(os.Args) <2 {
fmt.Println("Usage: ./md5file yourfile")
return
}
md5Value, err := Md5SumFile(os.Args[1])
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Printf("%x %s\n", md5Value, os.Args[1])
}
执行程序输出如下面所示:
$ go run src/md5_files.go src/test.txt
fc3ff98e8c6a0d3087d515c0473f8677 src/test.txt
2 文件的遍历与计算
2.1 参数处理
如果我们传递进去的是一个文件夹则如何处理呢?这里我们先通过改造原始的程序使得程序可以接收不同的参数类型比如-d代表了后面的为一个目录文件,-f代表了传递的是一个文件,这里我们需要借助于golang的flags包来完成参数的解析,解析完毕后我们就可以按照对应的方式处理参数了。
var directory, file *string
func init() {
directory = flag.String("d", "", "The directory contains all the files that need to calculate the md5 value")
file = flag.String("f", "", "The file that need to caclulate the md5 value")
}
func main() {
flag.Parse()
if *directory == "" && *file == "" {
flag.Usage()
return
}
if *file != "" {
md5Value, err := Md5SumFile(*file)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Printf("%x %s\n", md5Value, *file)
return
}
if *directory != "" {
result, err := Md5SumFolder(*directory)
if err != nil {
fmt.Println(err.Error())
return
}
var paths []string
for path := range result {
paths = append(paths, path)