2 回答
TA贡献1812条经验 获得超5个赞
原始代码不限制活动 go 例程的数量,因此不限制打开的文件描述符的数量。一些操作系统对打开的文件描述符的数量有限制。解决方法是创建固定数量的工作程序 go 例程。
func uploadDir(path string) error {
// Read directory and close.
dir, err := os.Open(path)
if err != nil {
return err
}
names, err := dir.Readdirnames(-1)
if err != nil {
return err
}
dir.Close()
// Copy names to a channel for workers to consume. Close the
// channel so that workers stop when all work is complete.
namesChan := make(chan string, len(names))
for _, name := range names {
namesChan <- name
}
close(namesChan)
// Create a maximum of 8 workers
workers := 8
if len(names) < workers {
workers = len(names)
}
errChan := make(chan error, 1)
resChan := make(chan *client.PutResult, len(names))
// Run workers
for i := 0; i < workers; i++ {
go func() {
// Consume work from namesChan. Loop will end when no more work.
for name := range namesChan {
file, err := os.Open(filepath.Join(path, name))
if err != nil {
select {
case errChan <- err:
// will break parent goroutine out of loop
default:
// don't care, first error wins
}
return
}
c := client.NewClient(os.Getenv("DROPS_SERVER"))
res, err := c.Upload(client.NewUploadHandleFromReader(file))
file.Close()
if err != nil {
select {
case errChan <- err:
// will break parent goroutine out of loop
default:
// don't care, first error wins
}
return
}
resChan <- res
}
}()
}
// Collect results from workers
for i := 0; i < len(names); i++ {
select {
case res := <-resChan:
log.Println(res)
case err := <-errChan:
return err
}
}
return nil
}
作为奖励,我修改了通道大小并发送操作,以便在出现错误时不会卡住 goroutine。
- 2 回答
- 0 关注
- 212 浏览
添加回答
举报