go-runewidth 使用指南
go-runewidth 是一个用于计算字符串显示宽度的 Go 语言库,特别适合处理多字节字符(如中文、日文等)的宽度计算。它能够正确处理全角字符(通常占2个显示宽度)和半角字符(通常占1个显示宽度)。
安装
go get github.com/mattn/go-runewidth
基本用法
1. 获取字符串显示宽度
package main
import (
"fmt"
"github.com/mattn/go-runewidth"
)
func main() {
// 计算字符串的显示宽度
str := "Hello, 世界"
width := runewidth.StringWidth(str)
fmt.Printf("'%s' 的显示宽度: %d\n", str, width)
// 输出: 'Hello, 世界' 的显示宽度: 11
// 解释: "Hello, " 7个半角字符(7) + "世界" 2个全角字符(4) = 11
}
2. 截断字符串到指定宽度
func main() {
str := "Hello, 世界"
// 截断字符串到指定宽度
truncated := runewidth.Truncate(str, 8, "...")
fmt.Printf("截断到8宽度: '%s'\n", truncated)
// 输出: 截断到8宽度: 'Hello, 世...'
truncated2 := runewidth.Truncate(str, 9, "...")
fmt.Printf("截断到9宽度: '%s'\n", truncated2)
// 输出: 截断到9宽度: 'Hello, 世界'
}
3. 填充字符串到指定宽度
func main() {
str := "你好"
// 填充字符串到指定宽度
padded := runewidth.FillRight(str, 10) // 右侧填充空格
fmt.Printf("填充到10宽度(右): '%s'\n", padded)
// 输出: 填充到10宽度(右): '你好 '
paddedLeft := runewidth.FillLeft(str, 10) // 左侧填充空格
fmt.Printf("填充到10宽度(左): '%s'\n", paddedLeft)
// 输出: 填充到10宽度(左): ' 你好'
}
4. 处理制表符宽度
func main() {
str := "Hello\t世界"
// 计算字符串宽度,考虑制表符
width := runewidth.StringWidth(str)
fmt.Printf("原始宽度: %d\n", width)
// 展开制表符
expanded := runewidth.ExpandTabs(str, 8)
fmt.Printf("展开制表符: '%s'\n", expanded)
expandedWidth := runewidth.StringWidth(expanded)
fmt.Printf("展开后宽度: %d\n", expandedWidth)
}
5. 处理emoji等特殊字符
func main() {
emoji := "🚀火箭"
width := runewidth.StringWidth(emoji)
fmt.Printf("'%s' 的显示宽度: %d\n", emoji, width)
// 输出: '🚀火箭' 的显示宽度: 6
// 解释: "🚀" 通常算作2宽度 + "火箭" 4宽度 = 6
}
高级用法
自定义字符宽度处理
func main() {
// 默认情况下,中文是2宽度
str := "中文"
fmt.Printf("默认宽度: %d\n", runewidth.StringWidth(str)) // 4
// 可以创建自定义条件
condition := runewidth.NewCondition()
condition.EastAsianWidth = false // 不按东亚宽度处理
fmt.Printf("非东亚宽度: %d\n", condition.StringWidth(str)) // 2
}
处理终端输出对齐
func main() {
items := []struct {
name string
price string
}{
{"苹果", "¥5"},
{"香蕉", "¥3"},
{"火龙果", "¥10"},
}
// 计算名称列最大宽度
maxNameWidth := 0
for _, item := range items {
w := runewidth.StringWidth(item.name)
if w > maxNameWidth {
maxNameWidth = w
}
}
// 打印对齐的表格
for _, item := range items {
padding := maxNameWidth - runewidth.StringWidth(item.name)
fmt.Printf("%s%s\t%s\n", item.name, strings.Repeat(" ", padding), item.price)
}
/* 输出:
苹果 ¥5
香蕉 ¥3
火龙果 ¥10
*/
}
注意事项
全角字符(如中文、日文等)通常计为2个显示宽度,半角字符计为1个
某些特殊字符(如emoji)的宽度可能因终端而异
制表符的宽度取决于制表位设置(通常为8个字符宽度)
组合字符(如带音标的字母)可能会影响宽度计算
go-runewidth 是构建命令行工具时处理多语言字符串对齐和格式化的理想选择,特别适合需要精确控制终端输出的场景。