zoukankan      html  css  js  c++  java
  • 【玩转Golang】reflect.DeepEqual

    如果有两个map,内容都一样,只有顺序不同

    m1:=map[string]int{"a":1,"b":2,"c":3};
    m2:=map[string]int{"a":1,"c":3,"b":2};

    我们怎么判断二者是否一致呢?

    如果你打算这么写:

    fmt.Println("m1==m2",m1==m2)

    这是行不通的,go没有重写map的==操作符,编译器会报告错误:

     invalid operation: m1 == m2 (map can only be compared to nil)

    意思是map的变量只能和空(nil)比较,例如:

    fmt.Println("m1 == nil?",m1==nil)
    fmt.Println("m2 != nil?",m2!=nil)

    这没有问题,执行结果是:

    Running...

    m1 == nil? false
    m2 != nil? true

    那怎么比较呢?如果要编程实现,还真是麻烦,比如我的想法是:循环m1,看看每个key是否都在m2中存在,再比较m1[key]是否和m2[key]相等,如果都ok,再依次循环m2。还真是麻烦:

    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;
    }

    其实,go的反射包中有一个巨好用的武器reflect.DeepEqual,可以方便解决这个问题,请看:

    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;
    }

    执行结果:

    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.

    但是美中不足的是,由于reflect.DeepEqual需要经过反射操作,效率比我们自己写的函数差的多了,写个简单的测试:

            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)    
    

     看看结果,大约有10倍的差距

    100000 call cmpMap(m1,m2) elapsed= 75.544992ms
    100000 call reflect.DeepEqual(m1,m2) elapsed= 735.577069ms

    当然,在一般情况下,这点儿性能损失不算什么,尤其在不确定类型需要反射的时候,更是我们不可不用的强大工具。

    比如:

    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"]));
    }

    执行结果:

    Running...
    
    reflect.DeepEqual(m1["a"],m2["a"] false
    reflect.DeepEqual(m1["b"],m2["b"] true

    这种情况,如果我们自己写代码比较,势必要使用switch type语法,实在是太麻烦了,感谢go包含了这么好的工具。

  • 相关阅读:
    百度云盘下载限速破解
    (五)Struts之Action类基础(二)
    (四)Decorator设计模式解决GET/POST请求的乱码问题(转)
    (三)Struts之Action类基础(一)
    (二)Struts.xml文件详解
    (一)Struts2 基础
    (三十一)web 开发基础项目
    mysql的索引
    数据库的acid
    String StringBuffer和StringBuilder
  • 原文地址:https://www.cnblogs.com/dajianshi/p/4220332.html
Copyright © 2011-2022 走看看