gpt4 book ai didi

concurrency - Golang并发下载死锁

转载 作者:数据小太阳 更新时间:2023-10-29 03:33:28 28 4
gpt4 key购买 nike

我想在 go 中并行下载文件,但我的代码永远不会退出:

package main

import (
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"sync"
)

func download_file(file_path string, wg sync.WaitGroup) {
defer wg.Done()
resp, _ := http.Get(file_path)
defer resp.Body.Close()
filename := filepath.Base(file_path)
file, _ := os.Create(filename)
defer file.Close()

size, _ := io.Copy(file, resp.Body)
fmt.Println(filename, size, resp.Status)
}

func main() {
var wg sync.WaitGroup

file_list := []string{
"http://i.imgur.com/dxGb2uZ.jpg",
"http://i.imgur.com/RSU6NxX.jpg",
"http://i.imgur.com/hUWgS2S.jpg",
"http://i.imgur.com/U8kaix0.jpg",
"http://i.imgur.com/w3cEYpY.jpg",
"http://i.imgur.com/ooSCD9T.jpg"}
fmt.Println(len(file_list))
for _, url := range file_list {
wg.Add(1)
fmt.Println(wg)
go download_file(url, wg)

}
wg.Wait()
}

这是什么原因?我看过这里:Golang download multiple files in parallel using goroutines但我没有找到解决办法。调试此类代码的最佳方法是什么?

最佳答案

正如 Tim Cooper 所说,您需要将 WaitGroup 作为指针传递。如果你在你的代码上运行 go vet 工具,它会给你这个警告:

$ go vet ex.go
ex.go:12: download_file passes Lock by value: sync.WaitGroup contains sync.Mutex
exit status 1

我建议使用可以在您保存文件时为您执行此操作的编辑器。例如go-plus用于 Atom。

至于代码,我认为你应该像这样重构它:

package main

import (
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"sync"
)

func downloadFile(filePath string) error {
resp, err := http.Get(filePath)
if err != nil {
return err
}
defer resp.Body.Close()

name := filepath.Base(filePath)

file, err := os.Create(name)
if err != nil {
return err
}
defer file.Close()

size, err := io.Copy(file, resp.Body)
if err != nil {
return err
}
fmt.Println(name, size, resp.Status)
return nil
}

func main() {
var wg sync.WaitGroup

fileList := []string{
"http://i.imgur.com/dxGb2uZ.jpg",
"http://i.imgur.com/RSU6NxX.jpg",
"http://i.imgur.com/hUWgS2S.jpg",
"http://i.imgur.com/U8kaix0.jpg",
"http://i.imgur.com/w3cEYpY.jpg",
"http://i.imgur.com/ooSCD9T.jpg"}
fmt.Println("downloading", len(fileList), "files")
for _, url := range fileList {
wg.Add(1)
go func(url string) {
err := downloadFile(url)
if err != nil {
fmt.Println("[error]", url, err)
}
wg.Done()
}(url)
}
wg.Wait()
}

我不喜欢传递 WaitGroup 并且更喜欢保持函数简单、阻塞和顺序,然后在更高级别将并发缝合在一起。这使您可以选择按顺序执行所有操作,而无需更改 downloadFile

我还添加了错误处理和固定名称,因此它们是驼峰式。

关于concurrency - Golang并发下载死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30139279/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com