【发布时间】:2022-01-09 23:51:31
【问题描述】:
我正在尝试使用公司的 api 将一堆文件上传到他们提供的存储服务。 (基本上到我的帐户)。我有很多文件,比如 40-50 之类的。
我得到了文件的完整路径并使用了os.Open,这样我就可以通过 io.Reader。我确实尝试在没有goroutines 的情况下使用client.Files.Upload(),但上传它们花了很多时间并决定使用goroutines。这是我尝试过的实现。当我运行程序时,它只会上传一个文件,该文件是最小的文件或等待很长时间的文件。它有什么问题?难道不是每次 for 循环运行它都会创建一个 goroutine 继续其循环并为每个 file 创建一个?如何使用goroutines 使其尽可能快?
var filePaths []string
var wg sync.WaitGroup
// fills the string of slice with fullpath of files.
func fill() {
filepath.Walk(rootpath, func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
filePaths = append(filePaths, path)
}
if err != nil {
fmt.Println("ERROR:", err)
}
return nil
})
}
func main() {
fill()
tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
oauthClient := oauth2.NewClient(context.TODO(), tokenSource)
client := putio.NewClient(oauthClient)
for _, path := range filePaths {
wg.Add(1)
go func() {
defer wg.Done()
f, err := os.Open(path)
if err != nil {
log.Println("err:OPEN", err)
}
upload, err := client.Files.Upload(context.TODO(), f, path, 0)
if err != nil {
log.Println("error uploading file:", err)
}
fmt.Println(upload)
}()
}
wg.Wait()
}
【问题讨论】:
-
在循环内部执行
path := path(复制字符串)go func() { ...上方的某处。或者你可以做go func(path string) { ... }(path)。并查看此FAQ 以获得解释。 -
...顺便说一句,您的错误“处理”不足。
-
如果网络或存储带宽是限制因素,同时上传所有文件不会为您带来更多带宽(尽管多个流可能在一定程度上有所帮助,但您应该确定那是什么,并且限制并发)
标签: api go concurrency goroutine