编辑
2024-07-11
Golang
0
请注意,本文编写于 84 天前,最后修改于 83 天前,其中某些信息可能已经过时。

Golang 1.22.2

在项目涉及到了一个功能点,就是文件的移动,最开始是在windows下使用,然后发布到linux,业务第一阶段文件是一个分区下,代码还能正常运行,后期文件太多,一个分区装不下了,这时扩容了一个新的分区,然后就出现了*LinkError.错误,看到源码才知道,在非Unix系统下即使在同一个目录,Rename 不是原子操作。,源代码说明如下:

go
// Rename renames (moves) oldpath to newpath. // If newpath already exists and is not a directory, Rename replaces it. // OS-specific restrictions may apply when oldpath and newpath are in different directories. // Even within the same directory, on non-Unix platforms Rename is not an atomic operation. // If there is an error, it will be of type *LinkError. func Rename(oldpath, newpath string) error { return rename(oldpath, newpath) }

不能使用这个方法来移动文件后,还有其他方式吗,目前处理的方案是先复制,然后再删除,实际使用下来的效率是低于最开始使用的Rename。 实例代码如下:

go
func MoveFile(srcDir, destDir, move string) { files, err := os.ReadDir(srcDir) if err != nil { return } for _, file := range files { fileName := file.Name() // 判断文件是否存在,如果存在则删除,否则则移动对应的文件 toPath := filepath.Join(destDir, fileName) srcPath := filepath.Join(srcDir, fileName) if move == "1" { log.Printf("Move file: %s\n", fileName) err := os.Rename(srcPath, toPath) if err != nil { log.Printf("Failed to move the file: %s\n", err) } } else { if _, err := os.Stat(toPath); err == nil { // 如果存在 err := os.Remove(srcPath) if err != nil { return } fmt.Printf("Deleted: %s\n", file.Name()) } else { // 不存在 srcPath := filepath.Join(srcDir, fileName) // 复制文件 if err := copyFile(srcPath, toPath); err != nil { fmt.Println("Failed to copy:", err) return } // 删除源文件 if err := os.Remove(srcPath); err != nil { fmt.Println("Failed to delete the original file:", err) return } } } } } func copyFile(src, dest string) error { // 打开源文件 srcFile, err := os.Open(src) if err != nil { log.Fatalf("Error opening source file: %v", err) return err } defer srcFile.Close() // 创建目标文件 dstFile, err := os.Create(dest) if err != nil { log.Fatalf("Error creating destination file: %v", err) return err } defer dstFile.Close() // 使用 bufio.NewReader 来提高读取性能 reader := bufio.NewReader(srcFile) // 复制文件内容 _, err = io.Copy(dstFile, reader) if err != nil { log.Fatalf("Error copying file: %v", err) return err } log.Println("File copied successfully") return nil }

本文作者:南月星河

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!