【问题标题】:String prefix of requested length in golang working with utf-8 symbolsgolang中请求长度的字符串前缀使用utf-8符号
【发布时间】:2017-09-05 14:23:59
【问题描述】:

有没有一些优雅的方法可以在 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 字符串?有这方面的图书馆吗?我该如何解决?有没有更好的解决方案?

【问题讨论】:

    标签: string go utf-8


    【解决方案1】:

    问题在于对string 进行切片是对表示字符串的UTF-8 编码字节切片进行切片,而不是对string 的字符或runes 进行切片;这也意味着如果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,只需使用for range 获得第一个cropLength 符文就足够了。
    • 调用strings.TrimRightFunc() 需要将[]rune 转换回string,然后再次执行字符串连接以生成结果。这可以通过手动循环 []rune 来避免,并且只创建一个返回的 string

    【讨论】:

      猜你喜欢
      • 2020-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-09
      • 1970-01-01
      • 1970-01-01
      • 2016-08-14
      • 1970-01-01
      相关资源
      最近更新 更多