【发布时间】:2021-11-19 14:25:12
【问题描述】:
我正在构建一些东西来监视文件上传的目录。现在我正在使用 for {} 循环不断读取目录以进行测试,并计划在未来使用 cron 或其他东西来启动我的应用程序。
目标是监控上传目录,确保文件已完成复制,然后将文件移动到另一个目录进行处理。这些文件本身的大小从 15GB 到大约 50GB 不等,我们每天会收到数百个。
这是我第一次涉足围棋程序。我不确定我是否完全误解了 go 例程、通道和等待组或其他东西,但我认为当我遍历文件列表时,每个文件都会由 goroutine 函数独立处理。但是,当我运行下面的代码时,它会抓取一个文件,但只确认它在目录中找到的第一个文件。我注意到,一旦第一个文件完成,其他文件就会被确认为已完成。
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"sync"
"time"
"gopkg.in/yaml.v2"
)
type Config struct {
LogFileName string `yaml:"logfilename"`
LogFilePath string `yaml:"logfilepath"`
UploadRoot string `yaml:"upload_root"`
TPUploadTool string `yaml:"tp_upload_tool"`
}
var wg sync.WaitGroup
const WORKERS = 5
func getConfig(fileName string) (*Config, error) {
conf := &Config{}
yamlFile, err := os.Open(fileName)
if err != nil {
fmt.Printf("Error reading YAML file: %s\n", err)
os.Exit(1)
}
defer yamlFile.Close()
yaml_decoder := yaml.NewDecoder(yamlFile)
if err := yaml_decoder.Decode(conf); err != nil {
return nil, err
}
return conf, err
}
func getFileData(fileToUpload string, fileStatus chan string) {
var newSize int64
var currentSize int64
currentSize = 0
newSize = 0
fmt.Printf("Uploading: %s\n", fileToUpload)
fileDone := false
for !fileDone {
fileToUploadStat, _ := os.Stat(fileToUpload)
currentSize = fileToUploadStat.Size()
//fmt.Printf("%s current size is: %d\n", fileToUpload, currentSize)
//fmt.Println("New size ", newSize)
if currentSize != 0 {
if currentSize > newSize {
newSize = currentSize
} else if newSize == currentSize {
fileStatus <- "Done"
fileDone = true
wg.Done()
}
}
time.Sleep(1 * time.Second)
}
}
func sendToCDS() {
fmt.Println("Sending To CDS")
}
func main() {
fileStatus := make(chan string)
configFileName := flag.String("config", "", "YAML configuration file.\n")
flag.Parse()
if *configFileName == "" {
flag.PrintDefaults()
os.Exit(1)
}
UploaderConfig, err := getConfig(*configFileName)
if err != nil {
log.Fatal("Error reading configuration file.")
}
for {
fmt.Print("Checking for new files..")
uploadFiles, err := ioutil.ReadDir(UploaderConfig.UploadRoot)
if err != nil {
log.Fatal(err)
}
if len(uploadFiles) == 0 {
fmt.Println("..no files to transfer.\n")
}
for _, uploadFile := range uploadFiles {
wg.Add(1)
fmt.Println("...adding", uploadFile.Name())
if err != nil {
log.Fatalln("Unable to read file information.")
}
ff := UploaderConfig.UploadRoot + "/" + uploadFile.Name()
go getFileData(ff, fileStatus)
status := <-fileStatus
if status == "Done" {
fmt.Printf("%s is done.\n", uploadFile.Name())
os.Remove(ff)
}
}
wg.Wait()
}
}
我曾考虑将通道用于线程安全排队机制,该机制加载目录中的文件,然后文件被工作人员拾取。我在 Python 中做过类似的事情。
【问题讨论】:
-
我觉得不用channel,wait group就够了。
-
是的,我看到人们使用频道作为工作/工作队列来做类似于我正在尝试做的事情的不同示例。我不确定等待小组是否会完成同样的事情。
标签: go