golang获取字符或字符串固定宽度计算插件库go-runewidth的使用

golang获取字符或字符串固定宽度计算插件库go-runewidth的使用

go-runewidth 是一个用于获取字符或字符串固定宽度的Golang库,特别适合处理包含全角字符、emoji等不同宽度字符的场景。

功能特点

  • 计算字符串在终端显示时的实际宽度
  • 正确处理全角字符(如中文、日文等)
  • 支持emoji等特殊字符的宽度计算

安装方法

go get github.com/mattn/go-runewidth

使用示例

基本用法

package main

import (
	"fmt"
	"github.com/mattn/go-runewidth"
)

func main() {
	// 计算字符串宽度
	width := runewidth.StringWidth("つのだ☆HIRO")
	fmt.Println(width) // 输出: 12

	// 计算中文字符串宽度
	chineseWidth := runewidth.StringWidth("你好世界")
	fmt.Println(chineseWidth) // 输出: 8

	// 计算包含emoji的字符串宽度
	emojiWidth := runewidth.StringWidth("Hello 😊")
	fmt.Println(emojiWidth) // 输出: 7
}

更完整的示例

package main

import (
	"fmt"
	"github.com/mattn/go-runewidth"
)

func main() {
	// 测试各种字符的宽度
	testStrings := []string{
		"Hello",       // 全半角字符
		"こんにちは",    // 日文
		"안녕하세요",    // 韩文
		"你好",        // 中文
		"Hello 😊",    // 包含emoji
		"12345",       // 数字
		"!@#$%",       // 符号
	}

	for _, s := range testStrings {
		width := runewidth.StringWidth(s)
		fmt.Printf("字符串: %s\n实际宽度: %d\n字符数: %d\n\n", s, width, len(s))
	}

	// 计算单个字符的宽度
	rune1 := 'A'
	rune2 := 'あ'
	rune3 := '😊'

	fmt.Printf("字符 '%c' 的宽度: %d\n", rune1, runewidth.RuneWidth(rune1)) // 1
	fmt.Printf("字符 '%c' 的宽度: %d\n", rune2, runewidth.RuneWidth(rune2)) // 2
	fmt.Printf("字符 '%c' 的宽度: %d\n", rune3, runewidth.RuneWidth(rune3)) // 2
}

高级用法:字符串截断

package main

import (
	"fmt"
	"github.com/mattn/go-runewidth"
)

func main() {
	// 将字符串截断到指定宽度
	str := "これはテストですThis is a test"
	
	// 截断到宽度10
	truncated := runewidth.Truncate(str, 10, "...")
	fmt.Println(truncated) // 输出: これは... (实际显示宽度为10)

	// 填充字符串到指定宽度
	padded := runewidth.FillRight("Hello", 10) + "|"
	fmt.Println(padded) // 输出: "Hello     |" (总宽度10)

	padded = runewidth.FillLeft("Hello", 10) + "|"
	fmt.Println(padded) // 输出: "     Hello|" (总宽度10)
}

注意事项

  1. 全角字符(如中文、日文等)的宽度通常为2
  2. 大多数emoji的宽度为2
  3. 普通ASCII字符的宽度为1

作者

Yasuhiro Matsumoto

许可证

MIT License


更多关于golang获取字符或字符串固定宽度计算插件库go-runewidth的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang获取字符或字符串固定宽度计算插件库go-runewidth的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


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
	*/
}

注意事项

  1. 全角字符(如中文、日文等)通常计为2个显示宽度,半角字符计为1个
  2. 某些特殊字符(如emoji)的宽度可能因终端而异
  3. 制表符的宽度取决于制表位设置(通常为8个字符宽度)
  4. 组合字符(如带音标的字母)可能会影响宽度计算

go-runewidth 是构建命令行工具时处理多语言字符串对齐和格式化的理想选择,特别适合需要精确控制终端输出的场景。

回到顶部