package main import ( "crypto/sha256" "encoding/hex" "fmt" "io" "os" ) type FileUtil struct{} func (fu *FileUtil) FileExists(path string) (bool, error) { _, err := os.Stat(path) if err == nil { return true, nil } if os.IsNotExist(err) { return false, nil } return false, err } func (fu *FileUtil) CalculateSHA256(filePath string) (string, error) { file, err := os.Open(filePath) if err != nil { return "", err } defer file.Close() hasher := sha256.New() if _, err := io.Copy(hasher, file); err != nil { return "", err } hashBytes := hasher.Sum(nil) return hex.EncodeToString(hashBytes), nil } func (fu *FileUtil) CheckAndDownloadFile(filePath, expectedChecksum string, downloadFunc func(string) error) error { exists, err := fu.FileExists(filePath) if err != nil { return err } if exists { checksum, err := fu.CalculateSHA256(filePath) if err != nil { return err } if checksum != expectedChecksum { fmt.Printf("UserWarning: %s exists, but the SHA256 checksum does not match; re-downloading the file\n", filePath) return downloadFunc(filePath) } } else { return downloadFunc(filePath) } return nil } func main() { const expectedChecksum = "EXPECTED_CHECKSUM_HERE" filePath := "/home/pan/.cache/whisper/large-v2.pt" fu := &FileUtil{} err := fu.CheckAndDownloadFile(filePath, expectedChecksum, func(path string) error { // Add your file download code here fmt.Println("Downloading file:", path) return nil }) if err != nil { panic(err) } }
io.Copy
是 Go 语言中的一个实用函数,用于将数据从 io.Reader
接口实现的对象(如文件)拷贝到 io.Writer
接口实现的对象。在这个例子中,hasher
是一个 sha256
哈希器,实现了 io.Writer
接口,而 file
是一个打开的文件,实现了 io.Reader
接口。
当调用 io.Copy(hasher, file)
时,数据从文件 file
逐步读取,然后逐步写入哈希器 hasher
。在这个过程中,哈希器根据写入的数据逐步计算哈希值。
最终,当所有数据都从文件中读取并写入哈希器时,io.Copy
返回,表示数据已成功拷贝。在这之后,您可以使用 hasher.Sum(nil)
获取计算出的哈希值。
此方法的优点是,它不需要一次性将整个文件加载到内存中,而是以流式方式处理数据,这在处理大文件时特别有用。
总结: io.Copy(hasher, file)
从打开的文件 file
读取数据,并将数据写入 hasher
,这样哈希器就可以逐步计算文件的 SHA256 哈希值。当所有数据处理完毕,hasher
就包含了文件的完整哈希值。