使用utf-8符号的golang中请求长度的字符串前缀

时间:2017-04-10 13:44:01

标签: string go utf-8

是否有一些优雅的方法来裁剪字符串并在golang中创建漂亮的字符串前缀?我有这个功能开始:

func prettyCrop(in string, cropLength int) string {
    if len(in) < cropLength {
        return in
    } else {
        in = in[0:cropLength]
        in = strings.TrimRightFunc(in, func(r rune) bool {
            if r == ' ' {
                return true
            }
            return false
        })
        return in + "…"
    }
}

它对于英文文本来说已经足够好了,但是有一些更复杂的问题。见这个例子:

prettyCrop("čřč čřč", 8) //čř?…

TrimRightFunc无法正常工作。我希望它返回čřč。为什么这个函数没有返回有效的utf-8字符串?有这个图书馆吗?我该如何解决?有更好的解决方案吗?

1 个答案:

答案 0 :(得分:2)

问题是切片string切片表示字符串的UTF-8编码字节切片,而不是rune的字符或string;这也意味着如果string包含由UTF-8编码中的多个字节表示的字符,则切片/切割string可能会导致UTF-8编码序列无效。

假设cropLength表示字符数限制(而不是字节数限制),您应首先将string转换为[]rune,然后对其进行操作:

func prettyCrop(in string, cropLength int) string {
    in2 := []rune(in)
    if len(in2) < cropLength {
        return in
    } else {
        in2 = in2[:cropLength]
        in = strings.TrimRightFunc(string(in2), func(r rune) bool {
            if r == ' ' {
                return true
            }
            return false
        })
        return in + "…"
    }
}

测试它:

for i := 0; i < 7; i++ {
    fmt.Println(prettyCrop("čřč čřč", i))
}

输出(在Go Playground上尝试):

…
č…
čř…
čřč…
čřč…
čřč č…
čřč čř…

效果说明:

以上示例并非“友好”,因为:

  • 它会将整个in字符串转换为[]rune,只需使用cropLength获取其第一个for range符文即可。
  • 调用strings.TrimRightFunc()需要将[]rune转换回string,然后再次执行字符串连接以生成结果。这可以通过手动循环[]rune来避免,并且只创建一个返回的string