Zero dependency cross platform (just needs basic ANSI codes and Unicode font support, and ANSI codes can be disabled too if needed) golang concurrent safe progress bar for terminal/CLIs, with 8x the resolution of others (8 steps per character).
Shows a spinner and/or a progress bar with optional prefix and extra info.
Also provides reader/writer wrappers to automatically show progress of downloads/uploads or other io operations. As well as a Writer that can be used concurrently with the progress bar to show other output on screen.
Manually handling a 2 lines output updates (1 misc line and the 1 line for the progress bar)
pb := progressbar.NewBar()
fmt.Print("Progress bar example\n\n") // 1 empty line before the progress bar, for the demo
n := 1000
for i := 0; i <= n; i++ {
pb.ProgressBar(100. * float64(i) / float64(n))
if i%63 == 0 {
progressbar.MoveCursorUp(1)
fmt.Printf("Just an extra demo print for %d\n", i)
}
time.Sleep(20 * time.Millisecond)
}
Source: example/example.go (-moveup
mode)
pb := progressbar.NewBarWithWriter(os.Stdout)
w := pb.Writer()
fmt.Fprintln(w, "Progress bar example")
// demonstrate concurrency safety:
go PrintStuff(w, *everyFlag)
// exact number of 'pixels', just to demo every smooth step:
n := pb.Width * 8
for i := 0; i <= n; i++ {
pb.ProgressBar(100. * float64(i) / float64(n))
time.Sleep(*delayFlag)
}
go run fortio.org/progressbar/example@latest -color
Produces
Or without color:
◅███████████████████████████▊ ▻ 69.4%
Source: example/example.go (default mode)
reader := progressbar.NewAutoReader(progressbar.NewBar(), resp.Body, resp.ContentLength)
_, err = io.Copy(os.Stdout, reader)
reader.Close()
See it in action with a progress bar while downloading a URL:
go run fortio.org/progressbar/auto_example@latest https://go.dev/ > go_dev.html
Will show a progress bar for instance
$ go run ./auto_example https://go.dev/dl/go1.24.1.src.tar.gz > /dev/null
Fetching https://go.dev/dl/go1.24.1.src.tar.gz
⣾ █████████████████████▌ 53.7% 15.766 Mb out of 29.352 Mb, 293ms elapsed, 53.790 Mb/s, 253ms remaining
Source (now includes a multi bar separating R/W): auto_example/auto_example.go
mbar := progressbar.NewMultiBar(
os.Stdout,
1, // 1 extra line between bars by default.
"b1",
"longest prefix",
"short",
"b4",
)
wg := sync.WaitGroup{}
for i, bar := range mbar {
wg.Add(1)
// Update at random speed so bars move differently for a demo:
delay := time.Duration(5+rand.IntN(40)) * time.Millisecond
bar.WriteAbove(fmt.Sprintf("\t\t\tBar %d delay is %v", i+1, delay))
go func(b *progressbar.State) {
UpdateBar(b, delay)
wg.Done()
}(bar)
}
wg.Wait()
progressbar.MultiBarEnd(mbar)
Complete source: multi_example/multi_example.go
You can see it in use in fortio/multicurl cli too.
If you have more advanced needs for TUI including raw mode input or readline, you can also see/use/have a look at
And still use this for a progress bar part.