问题
for i:=0;i<len(a);i++{
if a[i] != b[i]{
return false
}
}
and just
a == b
I've found that the same string have different address
a := "abc"
b := "abc"
println(&a)
println(&b)
answer is :
0xc420045f68
0xc420045f58
so == not using address to compare.
In fact, I would like to know how == compares two strings.
I am searching for a long time on net. But failed...
回答1:
You should use the ==
operator to compare strings. It compares the content of the string
values.
What you print is the address of a
and b
variables. Since they are 2 distinct non-zero size variables, their addresses cannot be the same by definition. The values they hold of course may or may not be the same. The ==
operator compares the values the variables hold, not the addresses of the variables.
Your solution with the loop might even result in a runtime panic, if the b
string is shorter than a
, as you index it with values that are valid for a
.
The built-in ==
operator will likely always outperform any loop, as that is implemented in architecture specific assembly code. It is implemented in the runtime
package, unexported function memequal()
.
Also note that the built-in comparison might even omit checking the actual contents of the texts if their string header points to the same data (and have equal length). There is no reason not to use ==
.
The only reason where a custom equal function for string
values would make sense is where the heuristics of your strings are known. E.g. if you know all the string values have the same prefix and they may only differ in their last character. In this case you could write a comparator function which only compares the last character of the strings to decide if they are equal (and only, optionally revert to actually compare the rest). This solution would of course not use a loop.
回答2:
Use the Go ==
operator for string
equality. The Go gc
and gccgo
compilers are optimizing compilers. The Go runtime
has been optimized.
This comment in the strings package documentation for the strings.Compare function is also relevant to equality:
Compare is included only for symmetry with package bytes. It is usually clearer and always faster to use the built-in string comparison operators ==, <, >, and so on.
In Go, the runtime
representation of a string
is a struct
:
type StringHeader struct {
Data uintptr // byte array pointer
Len int // byte array length
}
When you assign a Go string
value to a variable,
s := "ABC"
the memory location allocated for the variable s
is set to the value of a StringHeader
struct
describing the string
. The address of the variable, &s
, points to the struct
, not to the underlying byte array.
A comparison for Go string
equality compares the bytes of the underlying arrays, the values of *StringHeader.Data[0:StringHeader.Len]
.
In Go, we use the Go testing
package to benchmark performance. For example, comparing the Go ==
operator to two Go string
equality functions:
Output:
$ 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)
}
}
来源:https://stackoverflow.com/questions/50792777/using-the-symbol-in-golang-and-using-a-loop-to-compare-if-string-a-equals-str