- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我在 Ubuntu 13.04 上使用 go 1.1 devel
go version devel +ebe8bca920ad Wed May 15 15:34:47 2013 +1000 linux/386
根据 http://golang.org/doc/faq#goroutines
When a coroutine blocks, such as by calling a blocking system call, the run-time automatically moves other coroutines on the same operating system thread to a different, runnable thread so they won't be blocked.
我正在尝试编写一个下载器,它可以使用 goroutines 分 block 下载一个大文件这是我想出的最好的 goroutine:
func download(uri string, chunks chan int, offset int, file *os.file) {
for current := range chunks {
fmt.println("downloading range: ", current, "-", current+offset)
client := &http.client{}
req, _ := http.newrequest("get", uri, nil)
req.header.set("range: ", fmt.sprintf("bytes=%d-%d", current, current+offset))
resp, err := client.do(req)
if err != nil {
panic(err)
}
defer resp.body.close()
body, err := ioutil.readall(resp.body)
if err != nil {
panic(err)
}
file.write(body)
}
}
完整脚本可在 https://github.com/tuxcanfly/godown/blob/master/godown.go 获得
尽管文件正在正确下载和保存,但我可以看到第二个 block 开始了只有当第一个完成时。
分 block 下载不应该并行运行,还是我做错了什么?
最佳答案
您只有一个 goroutine 下载 block 。
第 64 行:
go download(*download_url, chunks, offset, file)
你可能想要的是:
for i := 0; i < *threads; i++ {
go download(*download_url, chunks, offset, file)
}
这将立即下载 *threads
个 block 。
并发工作后,您可能会注意到第 29 行没有按您的预期工作。如果 block 1 在 block 2 之前完成,则这些部分将被乱序写入。您可能想改用 http://golang.org/pkg/os/#File.WriteAt .
您的 Range header 也有两个问题。
通过将第 19 行从
req.Header.Set("Range: ", fmt.Sprintf("bytes=%d-%d", current, current+offset))
对此
req.Header.Set("Range: ", fmt.Sprintf("bytes=%d-%d", current, current+offset-1))
有关 Range header 的更多信息,我建议阅读 Section 14.35 in RFC2616
关于go - 为什么带有网络 I/O 的 goroutines 被阻塞了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16642799/
我是一名优秀的程序员,十分优秀!