1024programmer News (Transfer) Golangreflect.DeepEqual function: determine whether two values ​​are consistent

(Transfer) Golangreflect.DeepEqual function: determine whether two values ​​are consistent

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

This article is from the internet and does not represent1024programmerPosition, please indicate the source when reprinting:https://www.1024programmer.com/transfer-golangreflect-deepequal-function-determine-whether-two-values-are-consistent/

author: admin

Previous article
Next article

Leave a Reply

Your email address will not be published. Required fields are marked *

Contact Us

Contact us

181-3619-1160

Online consultation: QQ交谈

E-mail: [email protected]

Working hours: Monday to Friday, 9:00-17:30, holidays off

Follow wechat
Scan wechat and follow us

Scan wechat and follow us

Follow Weibo
Back to top
首页
微信
电话
搜索