在编程中,字符串在任何编程语言中的使用大概都是最频繁的了。Go 语言对字符串相关的操作也提供了大量的API,字符串可以向普通的 slice 一样进行相关操作,同时,也有标准库也专门提供一个 strings 包进行字符串的操作。
2022年3月15日,Go 1.18正式版发布,带来了很多特性,尤其是泛型的支持,带来很多便利,但是今天我们不谈泛型,主要来说说在 Go 1.18版本中,strings 包新增的两个API:Clone 和 Cut,这里我们主要谈一下 Cut 的使用。
Cut 函数的定义如下:
// Cut slices s around the first instance of sep,
// returning the text before and after sep.
// The found result reports whether sep appears in s.
// If sep does not appear in s, cut returns s, "", false.
func Cut(s, sep string) (before, after string, found bool)
将字符串 s 在第一个 sep 处切割成两部分,返回分割值 before 和 after。如果 s 中存在 sep,则返回 before,after,true,如果 s 中没有 sep,则返回 s,"",false。
比如现在有一个需求:从 example.rs@gmail.com 中获取 邮箱名称与 邮箱后缀。在 Go1.18 版本发布之前,我们实现的方式是:
package main
import (
"fmt"
"strings"
)
func main() {
email := "example.rs@gmail.com"
pos := strings.Index(addr, "@")
if pos == -1 {
fmt.Println("非法邮箱地址")
} else {
username, suffix := email[:pos], email[pos+1:]
fmt.Println(username, suffix)
}
}
而在 Go1.18 版本之后,我们就可以使用 Cut 来实现类似的功能:
package main
import (
"fmt"
"strings"
)
func main() {
addr := "example.rs@gmail.com"
username, suffix, found := strings.Cut(addr, ":")
if found {
fmt.Println(username, suffix)
} else {
fmt.Println("非法邮箱地址")
}
}
我们可以看下Cut的源代码:
func Cut(s, sep string) (before, after string, found bool) {
if i := Index(s, sep); i >= 0 {
return s[:i], s[i+len(sep):], true
}
return s, "", false
}
其实,可以看到,源代码的实现其实与我们上面的代码基本类似,只不过比上面写的更加凝练一些。将字符串 s 在第一个 sep 处切割成两部分,分别存储到 before 和 after 中。当字符串 s 中没有 sep时,before 则为 s,after 则为空,found 为false,即 s, "", false。 在用 Cut 时,我们一定得注意,如果 sep 多次出现时,依旧是以第一处为切割,其他的则不予处理,依旧出现在 after 中。
其实,官方提供的示例也很清楚的介绍了 Cut 的用法:
package main
import (
"fmt"
"strings"
)
func main() {
show := func(s, sep string) {
before, after, found := strings.Cut(s, sep)
fmt.Printf("Cut(%q, %q) = %q, %q, %v\n", s, sep, before, after, found)
}
show("Gopher", "Go")
show("Gopher", "ph")
show("Gopher", "er")
show("Gopher", "Badger")
}
/*
Output:
Cut("Gopher", "Go") = "", "pher", true
Cut("Gopher", "ph") = "Go", "er", true
Cut("Gopher", "er") = "Goph", "", true
Cut("Gopher", "Badger") = "Gopher", "", false
*/
可能有人会吐槽,Go 语言为了省一行代码居然出一个新的函数,是否有违Go语言的初衷呢?其实, Russ Cox 在关于 Cut 函数更加详细的阐述了一下理由:
可以看出,除了示例和测试数据之外,有311处索引调用可以使用 strings.Cut 用法。再排除一些确实不需要的剩下285处,而其中221处更加适合使用 Cut 方法的。也就是说,在现有的Go代码中,有77%可以用新增 Cut 方法来更清楚的使用。
更详细的你可以通过此链接去了解, github.com/golang/go/i…
除 strings 标准库之外,bytes 库中同样增加了 Cut 的方法,使用方式也与 strings 类似。