3 回答

TA貢獻1779條經驗 獲得超6個贊
您可以\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一次就足夠了,您可以將它存儲在一個(全局)變量中并重用它,從多個 goroutines 同時使用它甚至是安全的。
使用strings.Map()
另請注意,如果您只想替換(刪除)單個runes 而不是多符文(或多字節)子字符串,您還可以使用strings.Map()which 可能比strings.Replacer.
首先定義一個函數,告訴rune要替換哪些 s(如果返回負值則刪除):
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()它會更好,因為它只需要處理rune只是數字的 s int32,而strings.Replacer必須處理string標頭(長度+數據指針)加上一系列字節的值。
但是我們應該知道,string值在內存中存儲為 UTF-8 字節序列,這意味著strings.Map()必須rune從 UTF-8 字節序列中解碼 s(并最終將符文編碼回 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()因為它不需要解碼和編碼符文。

TA貢獻1818條經驗 獲得超3個贊
在當前的 Python(截至 2021 年 11 月)和 Windows 10 下,這段代碼對我有用:
s = str.replace(s, "\x00", "", -1)

TA貢獻1859條經驗 獲得超6個贊
我不知道這是否是您的情況,但就我而言,我收到了uint16來自 Windows Syscalls 的切片。在這種情況下,數據也由 null 元素終止。為了解決這個問題,你可以使用這個windows包:
package main
import (
? ?"fmt"
? ?"golang.org/x/sys/windows"
)
func main() {
? ?a := []uint16{77, 97, 114, 99, 104, 0}
? ?s := windows.UTF16ToString(a)
? ?fmt.Printf("%q\n", s) // "March"
}
- 3 回答
- 0 關注
- 194 瀏覽
添加回答
舉報