1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Deep equality test via reflection
11 // During deepValueEqual, must keep track of checks that are
12 // in progress. The comparison algorithm assumes that all
13 // checks in progress are true when it reencounters them.
14 // Visited comparisons are stored in a map indexed by visit.
21 // Tests for deep equality using reflected types. The map argument tracks
22 // comparisons that have already been seen, which allows short circuiting on
24 func deepValueEqual(v1
, v2 Value
, visited
map[visit
]bool, depth
int) bool {
25 if !v1
.IsValid() ||
!v2
.IsValid() {
26 return v1
.IsValid() == v2
.IsValid()
28 if v1
.Type() != v2
.Type() {
32 // if depth > 10 { panic("deepValueEqual") } // for debugging
34 // We want to avoid putting more in the visited map than we need to.
35 // For any possible reference cycle that might be encountered,
36 // hard(t) needs to return true for at least one of the types in the cycle.
37 hard
:= func(k Kind
) bool {
39 case Map
, Slice
, Ptr
, Interface
:
45 if v1
.CanAddr() && v2
.CanAddr() && hard(v1
.Kind()) {
46 addr1
:= unsafe
.Pointer(v1
.UnsafeAddr())
47 addr2
:= unsafe
.Pointer(v2
.UnsafeAddr())
48 if uintptr(addr1
) > uintptr(addr2
) {
49 // Canonicalize order to reduce number of entries in visited.
50 // Assumes non-moving garbage collector.
51 addr1
, addr2
= addr2
, addr1
54 // Short circuit if references are already seen.
56 v
:= visit
{addr1
, addr2
, typ
}
61 // Remember for later.
67 for i
:= 0; i
< v1
.Len(); i
++ {
68 if !deepValueEqual(v1
.Index(i
), v2
.Index(i
), visited
, depth
+1) {
74 if v1
.IsNil() != v2
.IsNil() {
77 if v1
.Len() != v2
.Len() {
80 if v1
.Pointer() == v2
.Pointer() {
83 for i
:= 0; i
< v1
.Len(); i
++ {
84 if !deepValueEqual(v1
.Index(i
), v2
.Index(i
), visited
, depth
+1) {
90 if v1
.IsNil() || v2
.IsNil() {
91 return v1
.IsNil() == v2
.IsNil()
93 return deepValueEqual(v1
.Elem(), v2
.Elem(), visited
, depth
+1)
95 if v1
.Pointer() == v2
.Pointer() {
98 return deepValueEqual(v1
.Elem(), v2
.Elem(), visited
, depth
+1)
100 for i
, n
:= 0, v1
.NumField(); i
< n
; i
++ {
101 if !deepValueEqual(v1
.Field(i
), v2
.Field(i
), visited
, depth
+1) {
107 if v1
.IsNil() != v2
.IsNil() {
110 if v1
.Len() != v2
.Len() {
113 if v1
.Pointer() == v2
.Pointer() {
116 for _
, k
:= range v1
.MapKeys() {
117 val1
:= v1
.MapIndex(k
)
118 val2
:= v2
.MapIndex(k
)
119 if !val1
.IsValid() ||
!val2
.IsValid() ||
!deepValueEqual(val1
, val2
, visited
, depth
+1) {
125 if v1
.IsNil() && v2
.IsNil() {
128 // Can't do better than this:
131 // Normal equality suffices
132 return valueInterface(v1
, false) == valueInterface(v2
, false)
136 // DeepEqual reports whether x and y are ``deeply equal,'' defined as follows.
137 // Two values of identical type are deeply equal if one of the following cases applies.
138 // Values of distinct types are never deeply equal.
140 // Array values are deeply equal when their corresponding elements are deeply equal.
142 // Struct values are deeply equal if their corresponding fields,
143 // both exported and unexported, are deeply equal.
145 // Func values are deeply equal if both are nil; otherwise they are not deeply equal.
147 // Interface values are deeply equal if they hold deeply equal concrete values.
149 // Map values are deeply equal when all of the following are true:
150 // they are both nil or both non-nil, they have the same length,
151 // and either they are the same map object or their corresponding keys
152 // (matched using Go equality) map to deeply equal values.
154 // Pointer values are deeply equal if they are equal using Go's == operator
155 // or if they point to deeply equal values.
157 // Slice values are deeply equal when all of the following are true:
158 // they are both nil or both non-nil, they have the same length,
159 // and either they point to the same initial entry of the same underlying array
160 // (that is, &x[0] == &y[0]) or their corresponding elements (up to length) are deeply equal.
161 // Note that a non-nil empty slice and a nil slice (for example, []byte{} and []byte(nil))
162 // are not deeply equal.
164 // Other values - numbers, bools, strings, and channels - are deeply equal
165 // if they are equal using Go's == operator.
167 // In general DeepEqual is a recursive relaxation of Go's == operator.
168 // However, this idea is impossible to implement without some inconsistency.
169 // Specifically, it is possible for a value to be unequal to itself,
170 // either because it is of func type (uncomparable in general)
171 // or because it is a floating-point NaN value (not equal to itself in floating-point comparison),
172 // or because it is an array, struct, or interface containing
174 // On the other hand, pointer values are always equal to themselves,
175 // even if they point at or contain such problematic values,
176 // because they compare equal using Go's == operator, and that
177 // is a sufficient condition to be deeply equal, regardless of content.
178 // DeepEqual has been defined so that the same short-cut applies
179 // to slices and maps: if x and y are the same slice or the same map,
180 // they are deeply equal regardless of content.
182 // As DeepEqual traverses the data values it may find a cycle. The
183 // second and subsequent times that DeepEqual compares two pointer
184 // values that have been compared before, it treats the values as
185 // equal rather than examining the values to which they point.
186 // This ensures that DeepEqual terminates.
187 func DeepEqual(x
, y
interface{}) bool {
188 if x
== nil || y
== nil {
193 if v1
.Type() != v2
.Type() {
196 return deepValueEqual(v1
, v2
, make(map[visit
]bool), 0)