golang终端应用进度条渲染插件库uiprogress的使用

Golang终端应用进度条渲染插件库uiprogress的使用

uiprogress是一个用于在终端应用程序中渲染进度条的Go库。它提供了一组灵活的功能和可定制的API。

特性

  • 多进度条:可以同时渲染和跟踪多个进度条
  • 动态添加:可以随时添加新的进度条,即使进度跟踪已经开始
  • 前置和后置功能:可以在进度条前后添加完成百分比和已用时间
  • 自定义装饰器函数:可以添加自定义函数和辅助函数来装饰进度条

基本用法

要开始使用进度条,首先调用uiprogress.Start(),然后使用uiprogress.AddBar(total int)添加进度条。使用bar.Incr()bar.Set(n int)来更新进度。

package main

import (
	"time"
	"github.com/gosuri/uiprogress"
)

func main() {
	uiprogress.Start()            // 开始渲染
	bar := uiprogress.AddBar(100) // 添加一个新进度条,总数为100

	// 可选:在进度条后添加完成百分比,前面添加已用时间
	bar.AppendCompleted()
	bar.PrependElapsed()

	for bar.Incr() {
		time.Sleep(time.Millisecond * 20)
	}
}

使用自定义装饰器

除了默认的bar.AppendCompleted()bar.PrependElapsed()装饰器外,你还可以添加自定义装饰器函数。

package main

import (
	"time"
	"github.com/gosuri/uiprogress"
)

func main() {
	var steps = []string{"下载源码", "安装依赖", "编译", "打包", "初始化数据库", "部署", "启动服务"}
	bar := uiprogress.AddBar(len(steps))

	// 在进度条前添加当前步骤
	bar.PrependFunc(func(b *uiprogress.Bar) string {
		return "应用: " + steps[b.Current()-1]
	})

	for bar.Incr() {
		time.Sleep(time.Millisecond * 10)
	}
}

渲染多个进度条

你可以使用uiprogress.AddBar(n)添加多个进度条。下面的例子展示了如何并发更新多个进度条,并在流程中后期添加新的进度条。

package main

import (
	"sync"
	"time"
	"github.com/gosuri/uiprogress"
)

func main() {
	waitTime := time.Millisecond * 100
	uiprogress.Start()

	// 在goroutine中启动进度条
	var wg sync.WaitGroup

	bar1 := uiprogress.AddBar(20).AppendCompleted().PrependElapsed()
	wg.Add(1)
	go func() {
		defer wg.Done()
		for bar1.Incr() {
			time.Sleep(waitTime)
		}
	}()

	bar2 := uiprogress.AddBar(40).AppendCompleted().PrependElapsed()
	wg.Add(1)
	go func() {
		defer wg.Done()
		for bar2.Incr() {
			time.Sleep(waitTime)
		}
	}()

	time.Sleep(time.Second)
	bar3 := uiprogress.AddBar(20).PrependElapsed().AppendCompleted()
	wg.Add(1)
	go func() {
		defer wg.Done()
		for i := 1; i <= bar3.Total; i++ {
			bar3.Set(i)
			time.Sleep(waitTime)
		}
	}()

	// 等待所有goroutine完成
	wg.Wait()
}

使用Incr计数器

Bar.Incr()是一个原子计数器,可以作为通用跟踪器使用,非常适合跟踪分发到多个goroutine的工作进度。

package main

import (
	"fmt"
	"math/rand"
	"runtime"
	"sync"
	"time"
	"github.com/gosuri/uiprogress"
)

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU()) // 使用所有可用的CPU核心

	// 创建一个新进度条,并在进度条前添加任务进度,然后分发到1k个goroutine
	count := 1000
	bar := uiprogress.AddBar(count).AppendCompleted().PrependElapsed()
	bar.PrependFunc(func(b *uiprogress.Bar) string {
		return fmt.Sprintf("任务 (%d/%d)", b.Current(), count)
	})

	uiprogress.Start()
	var wg sync.WaitGroup

	// 分发到goroutine
	for i := 0; i < count; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)))
			bar.Incr()
		}()
	}
	time.Sleep(time.Second) // 等待所有goroutine完成
	wg.Wait()
	uiprogress.Stop()
}

安装

$ go get -v github.com/gosuri/uiprogress

待办事项

  • 通过自动检测窗口尺寸来调整进度条和装饰器大小
  • 处理超出垂直屏幕允许范围的更多进度条

许可证

uiprogress基于MIT许可证发布。


更多关于golang终端应用进度条渲染插件库uiprogress的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang终端应用进度条渲染插件库uiprogress的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


uiprogress - Golang终端进度条库使用指南

uiprogress是一个简单易用的Golang终端进度条渲染库,适合在命令行应用中显示任务进度。下面我将详细介绍其使用方法并提供示例代码。

安装

go get github.com/gosuri/uiprogress

基本使用

1. 简单进度条

package main

import (
	"time"
	"github.com/gosuri/uiprogress"
)

func main() {
	uiprogress.Start() // 启动渲染器
	bar := uiprogress.AddBar(100) // 添加一个最大值为100的进度条

	// 可选:设置进度条格式
	bar.AppendCompleted()
	bar.PrependElapsed()

	for bar.Incr() { // 每次增加1
		time.Sleep(time.Millisecond * 20)
	}
}

2. 自定义进度条

bar := uiprogress.AddBar(100).
	PrependFunc(func(b *uiprogress.Bar) string {
		return fmt.Sprintf("任务(%d/%d)", b.Current(), b.Total)
	}).
	AppendFunc(func(b *uiprogress.Bar) string {
		return fmt.Sprintf("%.2f%%", b.CompletedPercent()*100)
	})

3. 多个并行进度条

func main() {
	uiprogress.Start()
	
	// 创建3个并行进度条
	var bars []*uiprogress.Bar
	for i := 0; i < 3; i++ {
		bars = append(bars, uiprogress.AddBar(100).
			PrependFunc(func(b *uiprogress.Bar) string {
				return fmt.Sprintf("任务 %d:", i+1)
			}))
	}

	// 模拟并行任务
	var wg sync.WaitGroup
	for i, bar := range bars {
		wg.Add(1)
		go func(bar *uiprogress.Bar, id int) {
			defer wg.Done()
			for bar.Incr() {
				time.Sleep(time.Millisecond * time.Duration(10*(id+1)))
			}
		}(bar, i)
	}
	wg.Wait()
}

高级功能

1. 自定义宽度

uiprogress.Width = 50 // 设置全局宽度

2. 自定义进度条字符

bar := uiprogress.AddBar(100).
	SetEmpty(' ').       // 空进度字符
	SetFill('▓').       // 填充字符
	SetHead('>').       // 头部字符
	SetLeftBorder('|').  // 左边框
	SetRightBorder('|')  // 右边框

3. 手动控制进度

bar := uiprogress.AddBar(100)
for i := 0; i <= 100; i++ {
	bar.Set(i) // 直接设置进度值
	time.Sleep(time.Millisecond * 50)
}

4. 完成后操作

bar := uiprogress.AddBar(100)
bar.SetOnComplete(func(b *uiprogress.Bar) {
	fmt.Println("\n任务完成!")
})

完整示例

package main

import (
	"fmt"
	"sync"
	"time"
	
	"github.com/gosuri/uiprogress"
)

func main() {
	uiprogress.Start() // 开始渲染
	defer uiprogress.Stop() // 程序退出时停止

	// 设置全局宽度
	uiprogress.Width = 60

	// 创建3个进度条模拟并行任务
	var bars []*uiprogress.Bar
	for i := 0; i < 3; i++ {
		bar := uiprogress.AddBar(100).
			PrependFunc(func(b *uiprogress.Bar) string {
				return fmt.Sprintf("任务 %d:", i+1)
			}).
			AppendFunc(func(b *uiprogress.Bar) string {
				return fmt.Sprintf("(%.1f%%)", b.CompletedPercent()*100)
			}).
			SetOnComplete(func(b *uiprogress.Bar) {
				fmt.Printf("\n任务 %d 已完成!\n", i+1)
			})
		
		// 自定义样式
		bar.SetEmpty(' ').
			SetFill('▓').
			SetHead('>').
			SetLeftBorder('[').
			SetRightBorder(']')
		
		bars = append(bars, bar)
	}

	// 模拟并行任务
	var wg sync.WaitGroup
	for i, bar := range bars {
		wg.Add(1)
		go func(bar *uiprogress.Bar, id int) {
			defer wg.Done()
			for i := 0; i <= 100; i++ {
				bar.Set(i)
				time.Sleep(time.Millisecond * time.Duration(50*(id+1)))
			}
		}(bar, i)
	}
	wg.Wait()
	
	fmt.Println("所有任务完成!")
}

注意事项

  1. 确保在程序退出前调用 uiprogress.Stop() 清理终端
  2. 在Docker容器中使用时可能需要设置 uiprogress.Out = os.Stderr
  3. 进度条不适合在非终端环境使用,应先检测 isatty.IsTerminal(os.Stdout.Fd())

uiprogress库简单易用,适合大多数命令行进度显示需求。对于更复杂的需求,可以考虑其他库如 cheggaaa/pbschollz/progressbar

回到顶部