2017-04-10 50 views
2

是否有一些优雅的方式来裁剪字符串并在golang中创建漂亮的字符串前缀?我有这个功能开始:使用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字符串?有这样的图书馆吗?我该如何解决它?有更好的解决方案吗?

回答

2

的问题是,一个切片切片string的UTF-8编码的字节切片表示该字符串,而不是字符或rune S上的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