Last active
October 9, 2025 16:56
-
-
Save hitalos/d2761d4552c7d398732693a580464da3 to your computer and use it in GitHub Desktop.
Golang progress bar
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 ( | |
| "fmt" | |
| "os" | |
| "strings" | |
| "time" | |
| "golang.org/x/term" | |
| ) | |
| var ( | |
| prefix = "Progress: " | |
| isTerm = term.IsTerminal(int(os.Stdout.Fd())) | |
| progressFormat = ternary(isTerm, "[\x1b[31m%s%s\x1b[0m]", "[%s%s]") // | |
| ) | |
| func main() { | |
| if isTerm { | |
| _, rows, _ := term.GetSize(int(os.Stdout.Fd())) | |
| fmt.Printf("\x1b[%dS\x1b[r", rows) // scroll one page and reset scrolling area | |
| } | |
| for i := 0.0; i <= 100; i++ { | |
| fmt.Println(i) | |
| progress(i, 100) | |
| time.Sleep(25 * time.Millisecond) | |
| } | |
| } | |
| func progress(current, total float64) { | |
| columns, rows, err := term.GetSize(int(os.Stdout.Fd())) | |
| if err != nil || columns < 40 { | |
| columns = 80 | |
| isTerm = false | |
| } | |
| if isTerm { | |
| fmt.Print("\x1b[s") // save cursor position | |
| fmt.Printf("\x1b[1;%dr", rows-1) // set scrolling area | |
| fmt.Printf("\x1b[%d;0H", rows) // go to last line | |
| } | |
| barSize := columns - len(prefix) - 22 | |
| done := strings.Repeat("#", int(current)*barSize/int(total)) | |
| rest := strings.Repeat(" ", barSize-len(done)) | |
| percent := float64(current) / float64(total) * 100 | |
| bar := fmt.Sprintf(progressFormat, done, rest) | |
| fmt.Printf("%s%s %.2f%% (%.f/%.f)\n", prefix, bar, percent, current, total) | |
| fmt.Printf("\x1b]2;%s%.2f%%\a", prefix, percent) // OSC escape code to set window | |
| if isTerm { | |
| if percent >= 100 { | |
| fmt.Print("\x1b[s") // save cursor position | |
| fmt.Print("\x1b[r") // reset scrolling area | |
| fmt.Println("\x1b[u") // restore cursor position and add a new line | |
| return | |
| } | |
| fmt.Printf("\x1b[u") // restore cursor position | |
| } | |
| } | |
| func ternary(cond bool, a, b string) string { | |
| if cond { | |
| return a | |
| } | |
| return b | |
| } |
Author
hitalos
commented
Sep 3, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment