Last active
August 9, 2022 17:14
-
-
Save kazimanzurrashid/1de68297833d4d9f3893c418c1f42bf4 to your computer and use it in GitHub Desktop.
Use workerpool to download multiple files concurrently from a json file in golang
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"urls": [ | |
"https://i.pinimg.com/236x/0d/a8/87/0da8872e1ca3e247aef7f75f64a75a5f--learn-coding-logos.jpg", | |
"https://www.evanmiller.org/images/four-days-of-go/gopher3.png", | |
"https://talks.golang.org/2013/highperf/aegopher.jpg", | |
"http://gophercloud.io/public/logo.png", | |
"https://forum.golangbridge.org/uploads/default/original/2X/0/03cbc1a9f9178055093eb0c25ba9df2c29611671.png", | |
"https://cdn.chrisshort.net/testing-certificate-chains-in-go/GOPHER_MIC_DROP.png" | |
] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"log" | |
"net/http" | |
"os" | |
"path" | |
"testdrive/workerpool" | |
) | |
const dataDir string = "./data" | |
type input struct { | |
URLs []string `json:"urls"` | |
} | |
func download(url string) bool { | |
res, err := http.Get(url) | |
if err != nil || res.StatusCode != http.StatusOK { | |
return false | |
} | |
defer func() { | |
_ = res.Body.Close() | |
}() | |
file, err := os.Create(path.Join(dataDir, path.Base(url))) | |
if err != nil { | |
panic(err) | |
} | |
defer func() { | |
_ = file.Close() | |
}() | |
if _, err = file.ReadFrom(res.Body); err != nil { | |
panic(err) | |
} | |
return true | |
} | |
func main() { | |
content, err := os.ReadFile(os.Args[1]) | |
if err != nil { | |
panic(err) | |
} | |
var input input | |
if err = json.Unmarshal(content, &input); err != nil { | |
panic(err) | |
} | |
_ = os.Mkdir(dataDir, os.ModeDir) | |
wp := workerpool.New(len(input.URLs), 3) | |
defer wp.Dispose() | |
wp.Run() | |
for _, url := range input.URLs { | |
func(url string) { | |
wp.Enqueue(func() { | |
log.Printf("Downloading: %v", url) | |
downloaded := download(url) | |
if downloaded { | |
log.Printf("Downloaded: %v", url) | |
} else { | |
log.Printf("Failed to download: %v", url) | |
} | |
}) | |
}(url) | |
} | |
wp.Wait() | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package workerpool | |
type WorkerPool struct { | |
total int | |
concurrent int | |
tasks chan func() | |
done chan bool | |
} | |
func (wp *WorkerPool) Run() { | |
for i := 0; i < wp.concurrent; i++ { | |
go func() { | |
for task := range wp.tasks { | |
task() | |
wp.done <- true | |
} | |
}() | |
} | |
} | |
func (wp *WorkerPool) Enqueue(task func()) { | |
wp.tasks <- task | |
} | |
func (wp *WorkerPool) Wait() { | |
for i := 0; i < wp.total; i++ { | |
<-wp.done | |
} | |
} | |
func (wp *WorkerPool) Dispose() { | |
close(wp.tasks) | |
close(wp.done) | |
} | |
func New(total, concurrent int) *WorkerPool { | |
return &WorkerPool{ | |
total: total, | |
concurrent: concurrent, | |
tasks: make(chan func()), | |
done: make(chan bool, total), | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment