Introduction:
For types such as array, slice, map, and struct, if you want to compare whether two values are equal, you cannot use ==. Perfectly solves the comparison problem.
Function signature:
func DeepEqual(a1, a2 interface{}) bool
The description of this function in the document:
The DeepEqual function is used to determine whether two values are consistent in depth: except for the same type; == will be used when possible (mainly basic types); but it will also compare array, Slice members, map key-value pairs, and structure fields are compared in depth. For the key-value pairs of the map, only == is used for the key, but the value will continue to be compared in depth. The DeepEqual function correctly handles the type of loop. Function types are equal only when they are all nil; empty slices are not equal to nil slices; the length of array and slice, and the number of map key-value pairs are also considered.
Example:
If there are two maps, the content is the same, only the order is different
m1:=map[string]int{"a":1,"b":2,"c":3}; m2:=map[string]int{"a":1,"c":3,"b":2};
How do we judge whether the two are consistent?
If you are going to write like this:
fmt.Println("m1==m2",m1==m2)
This won’t work, go doesn’t rewrite map’s == operator, the compiler will report an error:
invalid operation: m1 == m2 (map can only be compared to nil)
It means that the variable of map can only be compared with empty (nil), for example:
fmt.Println("m1 == nil?",m1==nil) fmt.Println("m2 != nil?",m2 !=nil)
There is no problem, the execution result is:
Running...
m1 == nil? false
m2 != nil? true
How do you compare? If you want to implement it by programming, it is really troublesome. For example, my idea is: loop m1 to see if each key exists in m2, and then compare whether m1[key] is equal to m2[key], if they are all ok, then follow Loop m2. It’s really troublesome:
func cmpMap(m1,m2 map[string]int)bool{ for k1,v1 :=range m1{ if v2,has:=m2[k1];has{ if v1!=v2 { return false } }else{ return false; } } for k2,v2:=range m2{ if v1,has:=m1[k2];has{ if v1!=v2{ return false; } }else{ return false; } } return true; }
In fact, there is a very useful weapon reflect.DeepEqual in go’s reflection package, which can easily solve this problem, please see:
package main import( "fmt" "reflect" ) type tt struct { Code int } func main(){ m1:=map[string]int{"a":1,"b":2,"c":3}; m2:=map[string]int{"a":1,"c":3,"b":2}; fmt.Println("m1 == nil?",m1==nil) fmt.Println("m2 != nil?",m2 != nil) //fmt.Println("m1==m2",m1==m2) fmt.Println("cmpMap(m1,m2) = ",cmpMap(m1,m2)); fmt.Println("reflect.DeepEqual(m1,m2) = ",reflect.DeepEqual(m1,m2)) fmt. Println() m3:=map[string]int{"a":1,"b":2,"c":3,"d":1}; fmt.Println("cmpMap(m1,m3)=",cmpMap(m1,m3)); fmt.Println("reflect.DeepEqual(m1,m3) = ",reflect.DeepEqual(m1,m3)) } func cmpMap(m1,m2 map[string]int) bool{ for k1,v1 :=range m1{ if v2,has:=m2[k1];has{ if v1!=v2 { return false } }else{ return false; } } for k2,v2:=range m2{ if v1,has:=m1[k2];has{ if v1!=v2{ return false; } }else{ return false; } } return true; }
Execution result:
Running... m1 == nil? false m2 != nil? true cmpMap(m1,m2) = true reflect.DeepEqual(m1,m2) = true cmpMap(m1,m3) = false reflect.DeepEqual(m1,m3) = false Success: process exited with code 0.
But the fly in the ointment is that since reflect.DeepEqual needs to undergo reflection operations, the efficiency is much worse than the functions we wrote ourselves. Write a simple test:
start:=time. Now(); for i:=0;i<100000;i++{ cmpMap(m1,m2) } end:=time. Now(); du:=end.Sub(start) fmt.Println("100000 call cmpMap(m1,m2) elapsed=",du) start=time. Now(); for i:=0;i<100000;i++{ reflect.DeepEqual(m1,m2); } end=time. Now(); du=end.Sub(start); fmt.Println("100000 call reflect.DeepEqual(m1,m2) elapsed=",du)
Look at the results, there is about a 10-fold difference
100000 call cmpMap(m1,m2) elapsed= 75.544992ms 100000 call reflect.DeepEqual(m1,m2) elapsed= 735.577069ms
Of course, under normal circumstances, this performance loss is nothing, especially when the uncertain type requires reflection, it is a powerful tool that we cannot use.
For example:
func main(){ m1:=map[string]interface{}{"a":"1", "b":2, "c":3}; m2:=map[string]interface{}{"a":1, "c":"3", "b":2}; fmt.Println(`reflect.DeepEqual(m1["a"],m2["a"]`,reflect.DeepEqual(m1["a"],m2["a"])); fmt.Println(`reflect.DeepEqual(m1["b"],m2["b"]`,reflect.DeepEqual(m1["b"],m2["b"])); }
Execution result:
Running... reflect.DeepEqual(m1["a"],m2["a"] false reflect.DeepEqual(m1["b"],m2["b"] true
In this case, if we write code comparison by ourselves, we must use the switch type syntax, which is really troublesome. Thanks to go for including such a good tool.
From: https://studygolang.com/articles/2194
Reference: https://blog.csdn.net/m0_37710023/article/details/108284171?utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.essearch_pc_relevant &depth_1-utm_source=distribute .pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.essearch_pc_relevant