跳至正文
首页 » Golang string 包中 Trim* 相关函数在使用中的一些坑

Golang string 包中 Trim* 相关函数在使用中的一些坑

起因

在某次开发中,我需要做到把一串字符从一个长字符串中删除掉,我自然的想到了 strings 包中的 Trim 相关函数,毕竟 Trim* 的意思是修剪。结果程序并没有按照我的想法进行,在网上查找 Trim* 相关用法,几乎没有找到这个坑,所以这里记录一下。

结论

先说结论,如果你也想删除某个字符串中的一个子串,那么请不要使用 Trim*,而是使用 Replace / ReplaceAll。

func main() {
 originString := "¡¡¡Hello, Gophers!!!"
 // 删除所有的 'e'
 fmt.Println(strings.ReplaceAll(originString, "e", "")) // ¡¡¡Hllo, Gophrs!!!
}

Trim 函数族

Trim / TrimLeft / TrimRight

他们都有一个共同点,就是要满足子串模式才会继续执行

先看一个例子

func main() {
 originString := "¡¡¡Hello, Gophers!!!"
 fmt.Println(strings.Trim(originString, "!¡"))   // Hello, Gophers // 1
 fmt.Println(strings.Trim(originString, "!e¡"))  // Hello, Gophers // 2
 fmt.Println(strings.Trim(originString, "!H¡"))  // ello, Gophers  // 3
 fmt.Println(strings.Trim(originString, "!Hs¡")) // ello, Gopher   // 4
}

Trim 内部的做法是

  1. 先根据第二个参数 cutset 形成一个 set
  2. 从左到右 + 从右到左遍历原始串,在遍历过程中遇到在 set 中的就删除,遇到没有的字符就返回
  3. 如果是 Trim 则会从左到右+从右到左执行,TrimLeft 和 TrimRight 则分别从左或者从右执行
// s 是原始串 as是根据 cutset 形成的 set
func trimLeftASCII(s string, as *asciiSet) string {
 // 遍历,如果没有break就走到最后
for len(s) > 0 {
 if !as.contains(s[0]) {
 break
   // 注意这里,如果原始串中的字符在 set 中没有就直接返回
   // 如上面的 2 号例子,走到 'H' 发现没在 set 中,就直接返回了
 }
  // 每次的更新原始串操作
 s = s[1:]
}
return s
}

TrimSuffix / TrimPrefix

与 Trim / TrimLeft / TrimRight 不同的是

这一族函数不会一直删,只会把前缀/后缀中包含的删除掉
如果前缀存在不同,则不会删除重叠部分,而是什么都不做

func main() {
 originString := "¡¡¡Hello, Gophers!!!"
 fmt.Println(strings.TrimPrefix(originString, "¡¡¡Hello, ")) // Gophers!!!      // 1
 fmt.Println(strings.TrimPrefix(originString, "¡¡¡"))        // Hello, Gophers!!!  // 2
 fmt.Println(strings.TrimPrefix(originString, "¡"))          // ¡¡Hello, Gophers!!! // 3
}

关键函数

func TrimPrefix(s, prefix string) string {
  // HasPrefix 是一个简单的前缀比较
 if HasPrefix(s, prefix) {
    // 只会删除前缀
  return s[len(prefix):]
 }
 return s
}

TrimFunc / TrimLeftFunc / TrimRightFunc

这些函数遍历原始串,根据 Func 中是否返回 true 来判断当前字符是否需要删除
例如:

func main() {
 fmt.Print(strings.TrimFunc("¡¡¡Hello, Gophers!!!", func(r rune) bool {
  return !unicode.IsLetter(r) && !unicode.IsNumber(r)
 }))
}
func IndexFunc(s string, f func(rune) bool) int {
  // 注意这里是 true
 return indexFunc(s, f, true)
}

TrimSpace

这个函数是删除所有 space,包括 \n \t在内的所有空格

func main() {
 fmt.Println(strings.TrimSpace(" \t\n Hello, Gophers \n\t\r\n"))
}Ï

最后

golang 的 stings 包,在业务中经常使用,如果拿不准还是要点进去仔细看一下,防止出现不符合预期的情况。

标签:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注