Go-TrimLeft-and-TrimPrefix
今天忽然发现了一个bug,其实是我自己的错误啦,不过也可以甩锅给文档……
简而言之,是用法错误,看这样一个例子:
package main
import (
"fmt"
"strings"
)
func main() {
str := "/some/key"
fmt.Println(strings.TrimLeft(str, "/some"))
}
key
Program exited.
https://play.golang.org/p/Hn8-iVEUi-W
没毛病是吧?
如果你也觉着没毛病,那你也错啦!
package main
import (
"fmt"
"strings"
)
func main() {
str := "/some/sugar"
fmt.Println(strings.TrimLeft(str, "/some"))
}
ugar
Program exited.
https://play.golang.org/p/_-3V1PgLwjh
喂喂喂!怎么把我的sugar的s给吃了,这是bug吧!
嗯。的确是bug,不过,“凡事总要先从自身找原因”:
func TrimLeft
func TrimLeft(s string, cutset string) string
TrimLeft returns a slice of the string s with all leading Unicode code points contained in cutset removed.
其实我一开始也觉着没错,毕竟,trim左边的嘛,但实际上,还有一个TrimPrefix
的函数:
TrimPrefix returns s without the provided leading prefix string. If s doesn’t start with prefix, s is returned unchanged.
这就很奇怪了, 为什么明明有一个可以用了, 还要再来一个?
em…
再读一下TrimLeft
的说明吧, 如果读不懂, 就再读再读再读, 直到发现自己不明白cutset
是什么意思.
— 分割线 —
看这个程序:
package main
import (
"fmt"
"strings"
)
func main() {
nodeOnlinePrefix := "/nodesli"
kvs := []string{
"/nodes/online/1ebbaa95eba5",
"/nodes/online/d39d0dd1c159",
"/nodes/online/d66b00076d8c",
}
nodes := []string{}
for _, v := range kvs {
str := fmt.Sprintf("%s", v)
fmt.Printf("online node got key %s\n", str)
n := strings.TrimLeft(str, nodeOnlinePrefix)
fmt.Printf("online node got node %s\n", n)
nodes = append(nodes, strings.TrimSpace(n))
}
fmt.Printf("online nodes: %v\n", nodes)
}
online node got key /nodes/online/1ebbaa95eba5
online node got node 1ebbaa95eba5
online node got key /nodes/online/d39d0dd1c159
online node got node 39d0dd1c159
online node got key /nodes/online/d66b00076d8c
online node got node 66b00076d8c
online nodes: [1ebbaa95eba5 39d0dd1c159 66b00076d8c]
https://play.golang.org/p/frClAL9oGrZ
这样, 是不是清晰了一点?
这个所谓的cutset
就是一个字符集, 而TrimLeft
就是从左开始, 如果发现了不在cutset
中的字符, 就从这个点返回.
比如有一个字符串 "1112345111"
, TrimLeft("1112345111", "1")
之后就成了 2345111
, 对应的, TrimRight("1112345111", "1")
就变成了"1112345"
; Trim("1112345111", "1")
则是从两头都砍, 返回的结果是"2345"
这是cutset
中只有一个字符的情况, 如果集合中有多个字符,那么就从里面开始匹配, 什么时候找不到了, 就返回.
那么怎么才能砍掉开头的一个"1"呢, 就是用TrimPrefix("1112345111", "1")
, 对应的, 除去末尾的话, 就用 TrimSuffix
.
有很多人也遇到了相同的问题, 感觉就是写文档的人和读文档的人认知有差别, 尤其是对cutset
的理解.
http://www.tapirgames.com/blog/golang-unofficial-faq#trim
呐, 有些事情不要想当然, 否则就是坑… (写代码容易, 修bug难!)