用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. 可访问性:提供选项禁用颜色效果

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

相关推荐
zhanggongzichu21 分钟前
小白怎么理解后端分层概念
后端·全栈
stark张宇1 小时前
Golang后端面试复盘:从Swoole到IM架构,如何支撑360w用户的实时消息推送?
后端
小码哥_常1 小时前
从0到1:搭建Spring Boot 3企业级认证授权平台
后端
小码哥_常2 小时前
告别扫库噩梦!Spring Boot+Redis让订单超时管理飞起来
后端
大傻^2 小时前
Spring AI Alibaba 快速入门:基于通义千问的AI应用开发环境搭建
java·人工智能·后端·spring·springai·springaialibaba
IT_陈寒3 小时前
SpringBoot实战:3个隐藏技巧让你的应用性能飙升50%
前端·人工智能·后端
彭于晏Yan3 小时前
MQTT消息服务
spring boot·后端·中间件
程序员Sunday3 小时前
Claude Code 生态爆发:5个必知的新工具
前端·人工智能·后端
weixin_387534224 小时前
Ownership - Rust Hardcore Head to Toe
开发语言·后端·算法·rust
前端付豪4 小时前
实现一个用户可以有多个会话
前端·后端·llm