在Go语言中解决并发文件备份问题可以使用协程和通道来实现。以下是一个示例代码:
package main import ( "io" "log" "os" "path/filepath" "sync" ) func main() { sourceDir := "./source" // 源文件目录 backupDir := "./backup" // 备份目录 concurrent := 5 // 并发数 // 创建备份目录 err := os.MkdirAll(backupDir, os.ModePerm) if err != nil { log.Fatal(err) } // 获取源文件列表 fileList, err := getFileList(sourceDir) if err != nil { log.Fatal(err) } // 创建并发控制通道 semaphore := make(chan struct{}, concurrent) // 创建等待组 var wg sync.WaitGroup // 备份文件 for _, file := range fileList { wg.Add(1) go func(file string) { // 限制并发数 semaphore <- struct{}{} defer func() { <-semaphore wg.Done() }() // 打开源文件 sourceFile, err := os.Open(filepath.Join(sourceDir, file)) if err != nil { log.Println(err) return } defer sourceFile.Close() // 创建目标文件 destFile, err := os.Create(filepath.Join(backupDir, file)) if err != nil { log.Println(err) return } defer destFile.Close() // 复制文件内容 _, err = io.Copy(destFile, sourceFile) if err != nil { log.Println(err) return } log.Println("备份文件完成:", file) }(file) } // 等待所有协程完成 wg.Wait() log.Println("备份完成") } // 获取目录下的文件列表 func getFileList(dir string) ([]string, error) { fileList := []string{} err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { relPath, err := filepath.Rel(dir, path) if err != nil { return err } fileList = append(fileList, relPath) } return nil }) if err != nil { return nil, err } return fileList, nil }
上述代码使用了协程和通道来实现并发备份文件的功能。首先,从源文件目录获取文件列表。然后,使用协程来并发备份每个文件,同时通过通道限制并发数。最后,使用等待组等待所有协程完成。
注意,在并发备份文件时,需要注意并发安全,避免多个协程同时操作同一个文件。在上述代码中,每个协程都会创建自己的源文件和目标文件,避免了并发安全问题。