用Go实现类似WinGet风格彩色进度条

用Go实现WinGet风格彩色进度条

命令行界面也可以很酷。受WinGet启发,我用Go实现了一个彩色渐变进度条,让终端交互更有活力。

终端色彩深度解析

ANSI转义码:终端的色彩语言

ANSI转义码始于1970年代,最初用于VT100终端。现代终端已支持24位真彩色:

bash 复制代码
# 基本格式
\033[38;2;R;G;Bm  # 设置前景色
\033[48;2;R;G;Bm  # 设置背景色
\033[0m           # 重置样式

# 示例:红色文字
echo -e "\033[38;2;255;0;0mHello World\033[0m"

终端兼容性矩阵

终端 真彩色支持 备注
iTerm2 macOS最佳体验
Windows Terminal Windows 10+
GNOME Terminal Linux主流
cmd.exe 仅支持16色
PowerShell Win10+支持真彩色

色彩心理学在CLI中的应用

  • 红色:警告、错误、高温
  • 绿色:完成、成功、安全
  • 蓝色:进行中、信息提示
  • 黄色:警告、需要注意

核心实现要点

颜色渐变算法

线性插值实现平滑过渡:

go 复制代码
func getGradientColor(start, end RGB, progress float64) RGB {
    r := start.R + int(float64(end.R-start.R)*progress)
    g := start.G + int(float64(end.G-start.G)*progress)
    b := start.B + int(float64(end.B-start.B)*progress)
    return RGB{r, g, b}
}

高效字符串构建

使用strings.Builder避免内存碎片:

swift 复制代码
var builder strings.Builder
builder.Grow(100) // 预分配内存
builder.WriteString("\033[38;2;")
// ... 拼接操作

光标控制技巧

  • \r:回车回到行首
  • \033[K:清除当前行
  • \033[A:上移一行

完整代码实现

go 复制代码
package main

import (
	"fmt"
	"math"
	"strings"
	"time"
)

type RGB struct{ R, G, B int }

type ProgressBar struct {
	Width      int
	StartColor RGB
	EndColor   RGB
	Title      string
}

func NewProgressBar(width int, start, end RGB, title string) *ProgressBar {
	return &ProgressBar{
		Width:      width,
		StartColor: start,
		EndColor:   end,
		Title:      title,
	}
}

func (p *ProgressBar) getColor(progress float64) RGB {
	progress = math.Max(0, math.Min(1, progress))
	r := p.StartColor.R + int(float64(p.EndColor.R-p.StartColor.R)*progress)
	g := p.StartColor.G + int(float64(p.EndColor.G-p.StartColor.G)*progress)
	b := p.StartColor.B + int(float64(p.EndColor.B-p.StartColor.B)*progress)
	return RGB{r, g, b}
}

func colorCode(rgb RGB) string {
	return fmt.Sprintf("\033[38;2;%d;%d;%dm", rgb.R, rgb.G, rgb.B)
}

const resetCode = "\033[0m"

func (p *ProgressBar) Render(progress float64) string {
	progress = math.Max(0, math.Min(1, progress))
	var builder strings.Builder
	builder.Grow(100)

	if p.Title != "" {
		builder.WriteString(p.Title)
		builder.WriteString(" ")
	}

	completed := int(float64(p.Width) * progress)
	for i := 0; i < completed; i++ {
		color := p.getColor(float64(i) / float64(p.Width))
		builder.WriteString(colorCode(color))
		builder.WriteString("█")
	}

	builder.WriteString(resetCode)
	
	percentColor := p.getColor(progress)
	builder.WriteString(colorCode(percentColor))
	builder.WriteString(fmt.Sprintf(" %d%%", int(progress*100)))
	builder.WriteString(resetCode)

	return builder.String()
}

func (p *ProgressBar) Show(progress float64) {
	fmt.Printf("\r%s", p.Render(progress))
	if progress >= 1.0 {
		fmt.Println()
	}
}

func main() {
	// 示例用法
	bar := NewProgressBar(40, 
		RGB{255, 50, 50}, 
		RGB{50, 255, 50}, 
		"下载:")
	
	for i := 0; i <= 100; i++ {
		bar.Show(float64(i) / 100)
		time.Sleep(30 * time.Millisecond)
	}
	
	fmt.Println("✅ 完成")
}

高级技巧

多段渐变支持

go 复制代码
func MultiGradient(colors []RGB, progress float64) RGB {
    segment := 1.0 / float64(len(colors)-1)
    idx := int(progress / segment)
    segmentProgress := (progress - float64(idx)*segment) / segment
    return getGradientColor(colors[idx], colors[idx+1], segmentProgress)
}

性能优化版本

对于需要高频更新的场景:

go 复制代码
func (p *ProgressBar) FastRender(progress float64) string {
    // 预计算颜色值,避免重复计算
    // 使用sync.Pool重用strings.Builder
}

实用场景

  1. 文件下载:红色→蓝色→绿色表示下载进度
  2. 数据处理:根据处理速度动态调整颜色
  3. 系统监控:CPU/内存使用率颜色预警
  4. 测试进度:测试通过率可视化

注意事项

  1. 终端检测 :运行时检查TERM环境变量
  2. 颜色回退:不支持真彩色时回退到16色
  3. 日志友好:重定向输出时自动禁用颜色
  4. 可访问性:提供选项禁用颜色效果

这个进度条不仅美观实用,更是终端图形化的一次有趣尝试。彩色让命令行不再单调,用户体验大幅提升。

相关推荐
卷无止境7 分钟前
从一个装饰器说起:拆解 Python 的 @property
后端·python
一只小小Java1 小时前
Naocs本地部署&安装3.2.3+Spring boot 3.2.0
java·spring boot·后端·nacos
码兄科技9 小时前
实战:基于Spring Boot + UniApp的地理信息小程序开发
spring boot·后端·uni-app
腾讯云云开发11 小时前
腾讯云 CloudBase 登上 WAIC:我们为 Agent 重新设计了云的生产线
后端
星栈11 小时前
从装一堆工具到看懂 Node 工程化思维:我的项目复盘记录
后端·node.js
65岁退休Coder11 小时前
LangChain v1.3.4 笔记 - 05 Agent 上下文记忆
后端
颜酱12 小时前
04 | 召回前置准备:搭好召回所需的四个数据库
前端·人工智能·后端
JaneConan12 小时前
鸿蒙 韶非 UI 系列:能力调用 startAbilityForResult,跳能力拿回参,鸿蒙能力路由入门
后端·harmonyos
晴空了无痕12 小时前
从 Go 基础到 K8s:一条可落地的 Go 服务端成长路线
开发语言·后端·golang·kubernetes
用户83562907805112 小时前
如何使用 Python 在 Excel 中添加、编辑和删除超链接
后端·python