您可以像删除任何其他符文一样从字符串中删除 \x00 符文:
valueStr = strings.Replace(valueStr, "\x00", "", -1)
例子:
s := "a\x00b"
fmt.Printf("%q\n", s)
s = strings.Replace(s, "\x00", "", -1)
fmt.Printf("%q\n", s)
输出(在Go Playground 上试试):
"a\x00b"
"ab"
使用strings.Replacer
还请注意,您可以使用 strings.Replacer 将多个替换替换为单个操作,并且它也将更有效,因为它只对输入进行一次迭代(并且将只分配一个 string结果,无论您要替换多少个子字符串)。
例如:
s := " \t\n\rabc\x00"
fmt.Printf("%q\n", s)
r := strings.NewReplacer(" ", "", "\t", "", "\n", "", "\r", "", "\x00", "")
s = r.Replace(s)
fmt.Printf("%q\n", s)
输出(在Go Playground上试试):
" \t\n\rabc\x00"
"abc"
还要注意,创建一个string.Replacer 一次就足够了,你可以将它存储在一个(全局)变量中并重复使用它,甚至可以安全地从多个 goroutine 中同时使用它。
使用strings.Map()
另外请注意,如果您只想替换(删除)单个runes 而不是多符文(或多字节)子字符串,您还可以使用strings.Map(),这可能比strings.Replacer 更有效.
首先定义一个函数,告诉要替换哪个runes(如果返回负值则删除):
func remove(r rune) rune {
switch r {
case ' ', '\t', '\n', '\r', 0:
return -1
}
return r
}
然后使用它:
s := " \t\n\rabc\x00"
fmt.Printf("%q\n", s)
s = strings.Map(remove, s)
fmt.Printf("%q\n", s)
输出(在Go Playground上试试):
" \t\n\rabc\x00"
"abc"
基准
我们可能认为strings.Map() 会更好,因为它只需要处理runes,它们只是int32 数字,而strings.Replacer 必须处理作为标题的string 值(长度+数据指针)加上一系列字节。
但我们应该知道,string 值在内存中存储为 UTF-8 字节序列,这意味着 strings.Map() 必须从 UTF-8 字节序列中解码 runes(并将符文编码回UTF-8 最后),而strings.Replacer 没有:它可能只是查找字节序列匹配而不解码runes。而strings.Replacer 经过高度优化,可以利用这些“技巧”。
让我们创建一个基准来比较它们:
我们会将这些用于基准测试:
var r = strings.NewReplacer(" ", "", "\t", "", "\n", "", "\r", "", "\x00", "")
func remove(r rune) rune {
switch r {
case ' ', '\t', '\n', '\r', 0:
return -1
}
return r
}
我们在不同的输入字符串上运行基准测试:
func BenchmarkReplaces(b *testing.B) {
cases := []struct {
title string
input string
}{
{
title: "None",
input: "abc",
},
{
title: "Normal",
input: " \t\n\rabc\x00",
},
{
title: "Long",
input: "adsfWR \t\rab\nc\x00 \t\n\rabc\x00asdfWER\n\r",
},
}
for _, c := range cases {
b.Run("Replacer-"+c.title, func(b *testing.B) {
for i := 0; i < b.N; i++ {
r.Replace(c.input)
}
})
b.Run("Map-"+c.title, func(b *testing.B) {
for i := 0; i < b.N; i++ {
strings.Map(remove, c.input)
}
})
}
}
现在让我们看看基准测试结果:
BenchmarkReplaces/Replacer-None-4 100000000 12.3 ns/op 0 B/op 0 allocs/op
BenchmarkReplaces/Map-None-4 100000000 16.1 ns/op 0 B/op 0 allocs/op
BenchmarkReplaces/Replacer-Normal-4 20000000 92.7 ns/op 6 B/op 2 allocs/op
BenchmarkReplaces/Map-Normal-4 20000000 92.4 ns/op 16 B/op 2 allocs/op
BenchmarkReplaces/Replacer-Long-4 5000000 234 ns/op 64 B/op 2 allocs/op
BenchmarkReplaces/Map-Long-4 5000000 235 ns/op 80 B/op 2 allocs/op
尽管有预期,string.Replacer 的性能相当不错,与 strings.Map() 一样好,因为它不必对符文进行解码和编码。