Comparing strings and bytes in Go without copying

What is the best way to verify that a Go string and a byte chunk contain the same bytes? The simplest str == string(byteSlice) inefficient since it first copies byteSlice .

I was looking for a version of Equal (a, b [] byte) that takes a string as its argument but cannot find anything suitable.

+6
source share
3 answers

Starting with Go 1.5, the compiler optimizes the string (bytes) compared to the string using temporary stack placement . Thus, since Go 1.5

 str == string(byteSlice) 

became a canonical and efficient way to compare strings with bytes.

+4
source

If you are comfortable enough with the fact that this might break on a later release (although doubtful), you can use 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 } 

playground

Benchmarks :

 // 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 
+5
source

Go programming language specification

String types

A string type is a collection of string values. A string value is an (possibly empty) byte sequence. Preferred string type string.

The length of the string s (its size in bytes) can be detected using the built-in len function. Access to string bytes can be obtained using integer indices from 0 to len (s) -1.

For instance,

 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)) } 

Output:

 true false 
+4
source

All Articles