Skip to content

Instantly share code, notes, and snippets.

@mrnugget
Created April 19, 2014 06:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mrnugget/11075703 to your computer and use it in GitHub Desktop.
Save mrnugget/11075703 to your computer and use it in GitHub Desktop.
Simple command line progress bar in Go
package main
import (
"flag"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"path"
"time"
)
const (
maxbars int = 100
interval time.Duration = 500 * time.Millisecond
)
var src string
type Progbar struct {
total int
}
func (p *Progbar) PrintProg(portion int) {
bars := p.calcBars(portion)
spaces := maxbars - bars - 1
percent := 100 * (float32(portion) / float32(p.total))
fmt.Print("\r[")
for i := 0; i < maxbars; i++ {
fmt.Print("=")
}
fmt.Print(">")
for i := 0; i <= spaces; i++ {
fmt.Print(" ")
}
fmt.Printf(" ] %3.2f%% (%d/%d)", percent, portion, p.total)
}
func (p *Progbar) PrintComplete() {
p.PrintProg(p.total)
fmt.Print("\n")
}
func (p *Progbar) calcBars(portion int) int {
if portion == 0 {
return portion
}
return int(float32(maxbars) / (float32(p.total) / float32(portion)))
}
func check(err error) {
if err != nil {
log.Fatal(err)
}
}
func init() {
flag.Parse()
src = flag.Args()[0]
}
func main() {
fmt.Printf("Downloading %s\n", src)
res, err := http.Get(src)
check(err)
defer res.Body.Close()
u, err := url.Parse(src)
check(err)
out, err := os.Create(path.Base(u.Path))
defer out.Close()
size := res.ContentLength
bar := &Progbar{total: int(size)}
written := make(chan int, 500)
go func() {
copied := 0
c := 0
tick := time.Tick(interval)
for {
select {
case c = <-written:
copied += c
case <-tick:
bar.PrintProg(copied)
}
}
}()
buf := make([]byte, 32*1024)
for {
rc, re := res.Body.Read(buf)
if rc > 0 {
wc, we := out.Write(buf[0:rc])
check(we)
if wc != rc {
log.Fatal("Read and Write count mismatch")
}
if wc > 0 {
written <- wc
}
}
if re == io.EOF {
break
}
check(re)
}
bar.PrintComplete()
fmt.Println("Download complete")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment