Counting work
func New(total int64, opts Options) *Barfunc (b *Bar) Advance(n int64)A bar counts units of work up to a total. The unit is yours: files, rows, requests or bytes.
Advance adds n to the count and returns. It never draws, so call it as often as you like.
bar := progress.New(int64(len(rows)), progress.Options{})bar.Start()for _, r := range rows { insert(r) bar.Advance(1)}err := bar.Stop()To count bytes, make the total a size and advance by every write. A small writer does it, so io.Copy drives
the bar:
// Command copy copies a file under a bar that counts the bytes.//// go run ./examples/copy <src> <dst>package main
import ( "errors" "fmt" "io" "log" "os"
"github.com/vardius/progress-go")
// copyFile copies src to dst. The bar's total is src's size, and it advances by every byte written.func copyFile(out io.Writer, dst, src string) error { in, err := os.Open(src) if err != nil { return err } defer in.Close() info, err := in.Stat() if err != nil { return err } to, err := os.Create(dst) if err != nil { return err }
bar := progress.New(info.Size(), progress.Options{Output: out}) bar.Start() _, err = io.Copy(io.MultiWriter(to, counter{bar}), in) if err != nil { err = fmt.Errorf("copy %s to %s: %w", src, dst, err) } return errors.Join(err, to.Close(), bar.Stop())}
// counter is a writer that advances a bar by the length of every write.type counter struct{ bar *progress.Bar }
func (c counter) Write(p []byte) (int, error) { c.bar.Advance(int64(len(p))) return len(p), nil}
func main() { log.SetFlags(0) if len(os.Args) != 3 { log.Fatal("usage: copy <src> <dst>") } if err := copyFile(os.Stdout, os.Args[2], os.Args[1]); err != nil { log.Fatal(err) }}io.MultiWriter writes to the file first, so the bar counts only bytes the file took.
Resuming
Section titled “Resuming”To pick up a job part way, advance by the work already done before Start:
bar := progress.New(size, progress.Options{Verbose: true})bar.Advance(alreadyDownloaded)bar.Start()The bar starts at that count. The time estimates count only the work done since Start, so the earlier work
doesn’t make them optimistic.
What the bar shows
Section titled “What the bar shows” 7/10 [███████████████████████████████████ ] 70%- The count is right-aligned to the width of the total, so it keeps its place as it grows.
- The bar is 50 cells. A cell fills for every 2% of the total, rounded down: 7 of 10 fills 35 cells.
- The percentage is rounded down, so 199 of 200 is 99%. It shows 100% only once the work is done.
The count always shows the true number, while the bar and the percentage stay within 0 and 100%:
| Count | Bar and percentage |
|---|---|
Above the total, such as 12/10 |
Full, 100% |
Below zero, after a negative Advance |
Empty, 0% |
| Any count, with a total of 0 or less | Full, 100%: there was nothing to do |
The maths is exact for any int64, the largest totals included.
Stopping part way
Section titled “Stopping part way”Stop draws the bar as it stands. A job that fails at 3 of 10 ends showing it:
3/10 [███████████████ ] 30%