![](/img/trans.png)
[英]How to use unsafe get a byte slice from a string without memory copy
[英]Compare string and byte slice in Go without copy
檢查 Go 字符串和字節切片是否包含相同字節的最佳方法是什么? 最簡單的str == string(byteSlice)
效率低下,因為它首先復制byteSlice
。
我正在尋找一個以字符串作為參數的Equal(a, b []byte)版本,但找不到任何合適的東西。
從 Go 1.5 開始,編譯器在與使用堆棧分配的臨時字符串進行比較時優化了字符串(字節)。 因此自從 Go 1.5
str == string(byteSlice)
成為將字符串與字節切片進行比較的規范且有效的方法。
如果您對這可能會在以后的版本中中斷這一事實感到滿意(盡管值得懷疑),您可以使用unsafe
:
func unsafeCompare(a string, b []byte) int {
abp := *(*[]byte)(unsafe.Pointer(&a))
return bytes.Compare(abp, b)
}
func unsafeEqual(a string, b []byte) bool {
bbp := *(*string)(unsafe.Pointer(&b))
return a == bbp
}
基准:
// using:
// aaa = strings.Repeat("a", 100)
// bbb = []byte(strings.Repeat("a", 99) + "b")
// go 1.5
BenchmarkCopy-8 20000000 75.4 ns/op
BenchmarkPetersEqual-8 20000000 83.1 ns/op
BenchmarkUnsafe-8 100000000 12.2 ns/op
BenchmarkUnsafeEqual-8 200000000 8.94 ns/op
// go 1.4
BenchmarkCopy 10000000 233 ns/op
BenchmarkPetersEqual 20000000 72.3 ns/op
BenchmarkUnsafe 100000000 15.5 ns/op
BenchmarkUnsafeEqual 100000000 10.7 ns/op
字符串類型表示字符串值的集合。 字符串值是一個(可能是空的)字節序列。 預先聲明的字符串類型是字符串。
可以使用內置函數 len 發現字符串 s 的長度(以字節為單位的大小)。 字符串的字節可以通過整數索引 0 到 len(s)-1 訪問。
例如,
package main
import "fmt"
func equal(s string, b []byte) bool {
if len(s) != len(b) {
return false
}
for i, x := range b {
if x != s[i] {
return false
}
}
return true
}
func main() {
s := "equal"
b := []byte(s)
fmt.Println(equal(s, b))
s = "not" + s
fmt.Println(equal(s, b))
}
輸出:
true
false
沒有理由使用 unsafe 包或其他東西來比較[]byte
和string
。 Go 編譯器現在足夠聰明,它可以優化此類轉換。
BenchmarkEqual-8 172135624 6.96 ns/op <--
BenchmarkUnsafe-8 179866616 6.65 ns/op <--
BenchmarkUnsafeEqual-8 175588575 6.85 ns/op <--
BenchmarkCopy-8 23715144 47.3 ns/op
BenchmarkPetersEqual-8 24709376 47.3 ns/op
只需將字節切片轉換為字符串並進行比較:
var (
aaa = strings.Repeat("a", 100)
bbb = []byte(strings.Repeat("a", 99) + "b")
)
func BenchmarkEqual(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = aaa == string(bbb)
}
}
👉這里有更多關於優化的信息,還有這個。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.