在golang中有个函数的定义如下:
func Trim(s, cutset string) string
按照官方文档的说明是:
Trim returns a slice of the string s with all leading and trailing Unicode code points contained in cutset removed.
stringslicecutset
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Trim("-----Hello, Gophers-----", "-"))
fmt.Println(strings.Trim("!-!-!-Hello, Gophers-!-!-!-!", "!-"))
fmt.Println(strings.Trim("!-!-!-Hello,-!-Go-!-!", "!-"))
}
得到的结果:
Hello, Gophers
Hello, Gophers
Hello,-!-Go
但是从正常理解来看,我认为的结果应该是:
Hello, Gophers
Hello, Gophers-!
Hello,-!-Go-!
那么问题到底出在哪里呢?
于是可以查看一下对应的源码:
// Trim returns a slice of the string s with all leading and
// trailing Unicode code points contained in cutset removed.
func Trim(s, cutset string) string {
if s == "" || cutset == "" {
return s
}
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0])
}
if as, ok := makeASCIISet(cutset); ok {
return trimLeftASCII(trimRightASCII(s, &as), &as)
}
return trimLeftUnicode(trimRightUnicode(s, cutset), cutset)
}
if
if as, ok := makeASCIISet(cutset); ok {
return trimLeftASCII(trimRightASCII(s, &as), &as)
}
as
type asciiSet [8]uint32
// makeASCIISet creates a set of ASCII characters and reports whether all
// characters in chars are ASCII.
func makeASCIISet(chars string) (as asciiSet, ok bool) {
for i := 0; i < len(chars); i++ {
c := chars[i]
if c >= utf8.RuneSelf {
return as, false
}
as[c/32] |= 1 << (c % 32)
}
return as, true
}
然后我们就可以开始准备一下恍然大悟了,直接和大家说结论吧,这个函数的功能有两个:
charsASCII8 * 32 = 256chars
as[c/32] |= 1 << (c%32)cuint32c%32
基于这个考虑我们可以编写这样的程序:
package main
import (
"fmt"
"unicode/utf8"
)
type asciiSet [8]uint32
func main() {
makeASCIISet("ababab")
makeASCIISet("ab")
makeASCIISet("baba")
}
// makeASCIISet creates a set of ASCII characters and reports whether all
// characters in chars are ASCII.
func makeASCIISet(chars string) (as asciiSet, ok bool) {
for i := 0; i < len(chars); i++ {
c := chars[i]
if c >= utf8.RuneSelf {
return as, false
}
as[c/32] |= 1 << (c % 32)
}
fmt.Println(as)
return as, true
}
然后就得到了这样的结果:
[0 0 0 6 0 0 0 0]
[0 0 0 6 0 0 0 0]
[0 0 0 6 0 0 0 0]
strings.Trim()
func trimLeftASCII(s string, as *asciiSet) string {
for len(s) > 0 {
if !as.contains(s[0]) {
break
}
s = s[1:]
}
return s
}
// contains reports whether c is inside the set.
func (as *asciiSet) contains(c byte) bool {
return (as[c/32] & (1 << (c % 32))) != 0
}
trimLeftASCIIasbreak
我们可以编写这个函数来验证一下:
package main
import (
"fmt"
"strings"
)
type asciiSet [8]uint32
func main() {
fmt.Println(strings.Trim("---a--Hello, Gophers-----", "-a"))
}
其中的返回结果:
Hello, Gophers
strings.Trim