Go言語で並行ファイルバックアップ問題を解決する方法
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
}
コルーチンとチャネルを利用してファイルを並列にバックアップする機能を実装したサンプルコードです。はじめに、ソースファイルのディレクトリからファイルのリストを取得します。その後、コルーチンを使って各ファイルを並行してバックアップしますが、チャネルを使用して同時実行数を制限します。最後に、待機グループを使用してすべての並行実行が完了するのを待ちます。
複数のgoroutineが同時に同じファイルに操作しないよう、並列バックアップファイルの際には注意が必要。上掲コードでは、各goroutineは独自のソースファイルとターゲットファイルを作成するため、並列安全問題を回避しています。