runtime: reflect.Value.Equal
This commit is contained in:
@@ -296,6 +296,80 @@ func (f flag) mustBeAssignableSlow() {
|
||||
}
|
||||
}
|
||||
|
||||
// Equal reports true if v is equal to u.
|
||||
// For two invalid values, Equal will report true.
|
||||
// For an interface value, Equal will compare the value within the interface.
|
||||
// Otherwise, If the values have different types, Equal will report false.
|
||||
// Otherwise, for arrays and structs Equal will compare each element in order,
|
||||
// and report false if it finds non-equal elements.
|
||||
// During all comparisons, if values of the same type are compared,
|
||||
// and the type is not comparable, Equal will panic.
|
||||
func (v Value) Equal(u Value) bool {
|
||||
if v.Kind() == Interface {
|
||||
v = v.Elem()
|
||||
}
|
||||
if u.Kind() == Interface {
|
||||
u = u.Elem()
|
||||
}
|
||||
|
||||
if !v.IsValid() || !u.IsValid() {
|
||||
return v.IsValid() == u.IsValid()
|
||||
}
|
||||
|
||||
if v.Kind() != u.Kind() || v.Type() != u.Type() {
|
||||
return false
|
||||
}
|
||||
|
||||
// Handle each Kind directly rather than calling valueInterface
|
||||
// to avoid allocating.
|
||||
switch v.Kind() {
|
||||
default:
|
||||
panic("reflect.Value.Equal: invalid Kind")
|
||||
case Bool:
|
||||
return v.Bool() == u.Bool()
|
||||
case Int, Int8, Int16, Int32, Int64:
|
||||
return v.Int() == u.Int()
|
||||
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
||||
return v.Uint() == u.Uint()
|
||||
case Float32, Float64:
|
||||
return v.Float() == u.Float()
|
||||
case Complex64, Complex128:
|
||||
return v.Complex() == u.Complex()
|
||||
case String:
|
||||
return v.String() == u.String()
|
||||
case Chan, Pointer, UnsafePointer:
|
||||
return v.Pointer() == u.Pointer()
|
||||
case Array:
|
||||
// u and v have the same type so they have the same length
|
||||
vl := v.Len()
|
||||
if vl == 0 {
|
||||
// panic on [0]func()
|
||||
if !v.Type().Elem().Comparable() {
|
||||
break
|
||||
}
|
||||
return true
|
||||
}
|
||||
for i := 0; i < vl; i++ {
|
||||
if !v.Index(i).Equal(u.Index(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case Struct:
|
||||
// u and v have the same type so they have the same fields
|
||||
nf := v.NumField()
|
||||
for i := 0; i < nf; i++ {
|
||||
if !v.Field(i).Equal(u.Field(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case Func, Map, Slice:
|
||||
break
|
||||
}
|
||||
panic("reflect.Value.Equal: values of type " + v.Type().String() + " are not comparable")
|
||||
}
|
||||
|
||||
// Addr returns a pointer value representing the address of v.
|
||||
// It panics if CanAddr() returns false.
|
||||
// Addr is typically used to obtain a pointer to a struct field
|
||||
|
||||
Reference in New Issue
Block a user