Используйте оператор Go ==
для равенства string
.Компиляторы Go gc
и gccgo
оптимизируют компиляторы.Go runtime
был оптимизирован.
Этот комментарий в документации пакета strings
для функции strings.Compare
также имеет отношение к равенству:
Сравнение включено только для симметрии с байтами пакета.Обычно проще и всегда быстрее использовать встроенные операторы сравнения строк ==, <,> и т. Д.
В Go runtime
представление string
- это struct
:
type StringHeader struct {
Data uintptr // byte array pointer
Len int // byte array length
}
Когда вы присваиваете значение Go string
переменной,
s := "ABC"
ячейка памяти, выделенная для переменной s
, равнаустановите значение StringHeader
struct
, описывающее string
.Адрес переменной &s
указывает на struct
, а не на базовый байтовый массив.
Сравнение для равенства Go string
сравнивает байты базовых массивов, значения *StringHeader.Data[0:StringHeader.Len]
.
В Go мы используем пакет Go testing
для оценки производительности.Например, сравнивая оператор Go ==
с двумя функциями равенства Go string
:
Вывод:
$ go test equal_test.go -bench=. -benchmem
BenchmarkEqualOper-4 500000000 3.19 ns/op 0 B/op 0 allocs/op
BenchmarkEqualFunc1-4 500000000 3.32 ns/op 0 B/op 0 allocs/op
BenchmarkEqualFunc2-4 500000000 3.61 ns/op 0 B/op 0 allocs/op
$ go version
go version devel +bb222cde10 Mon Jun 11 14:47:06 2018 +0000 linux/amd64
$
equal_test.go
:
package main
import (
"reflect"
"testing"
"unsafe"
)
func EqualOper(a, b string) bool {
return a == b
}
func EqualFunc1(a, b string) bool {
if len(a) != len(b) {
return false
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
func EqualFunc2(a, b string) bool {
if len(a) != len(b) {
return false
}
if len(a) == 0 {
return true
}
// string intern equality
if (*reflect.StringHeader)(unsafe.Pointer(&a)).Data == (*reflect.StringHeader)(unsafe.Pointer(&b)).Data {
return true
}
for i := 0; i < len(a); i++ {
if a[i] != b[i] {
return false
}
}
return true
}
var y, z = "aby", "abz"
func BenchmarkEqualOper(B *testing.B) {
a, b := y, z
for i := 0; i < B.N; i++ {
_ = EqualOper(a, b)
}
}
func BenchmarkEqualFunc1(B *testing.B) {
a, b := y, z
for i := 0; i < B.N; i++ {
_ = EqualFunc1(a, b)
}
}
func BenchmarkEqualFunc2(B *testing.B) {
a, b := y, z
for i := 0; i < B.N; i++ {
_ = EqualFunc2(a, b)
}
}