golang中使用interface{}类型进行比较的示例


使用golang开发应用必然躲不过interface{}类型,虽然golang 提供了类型断言和反射等方式解决类型转换的问题。

如果遇到“==”“!=”比较运算,空接口interface{}可以直接进行比较。接口类型的变量,包含该接口变量存储的值和值的类型两部分组成,分别称为接口的动态类型和动态值。只有动态类型和动态值都相同时,两个接口变量才相同。

测试代码如下:

package main

import "fmt"

type Foo struct {
    ID   int64
    Name string
    //Bytes []byte            //不能比较
    //Map   map[string]string //不能比较
    //Func  func() error      //不能比较
}

func main() {
    var _testNil, _testNil2 map[string]string
    struct1 := Foo{ID: 1, Name: "Sam"}
    _struct1 := Foo{ID: 1, Name: "Sam"}
    struct2 := Foo{ID: 1, Name: "Peter"}

    var data = []map[string]interface{}{
        {"params": []interface{}{1, 1}, "expected": true},
        {"params": []interface{}{2, 2, 2, 2, 2}, "expected": true},
        {"params": []interface{}{1, 2}, "expected": false},
        {"params": []interface{}{"1", 1}, "expected": false},
        {"params": []interface{}{nil, nil}, "expected": true},
        {"params": []interface{}{&_testNil, &_testNil2}, "expected": false},
        {"params": []interface{}{nil, _testNil}, "expected": false},
        //{"params": []interface{}{_testNil, _testNil2}, "expected": false},//slices、maps、functions类型不能参与比较,同样包含这三种类型的结构体也不能参与比较
        {"params": []interface{}{struct1, _struct1}, "expected": true},
        {"params": []interface{}{struct1, struct2}, "expected": false},
        {"params": []interface{}{&struct1, &struct1}, "expected": true},
        {"params": []interface{}{&struct1, &_struct1}, "expected": false},
    }

    for _, v := range data {
        result := compare(v["params"].([]interface{})...)
        fmt.Printf("expected:%t,result:%t,params:%#v\n", v["expected"].(bool), result, v["params"].([]interface{}))
    }
}

func compare(params ...interface{}) bool {
    if len(params) < 2 {
        return false
    }

    for i, v := range params {
        if i == 0 {
            continue
        }
        if params[0] != v {
            return false
        }
    }
    return true
}

值得注意的是,进行比较运算的时候,简单的类型和结构体都可以,但是不能是不可比较类型(uncomparable type),map、slice、func,以及包含这三种类型的结构体都不能参与比较。可以使用reflect.DeepEqual进行深度相等比较map、slice等类型。

总结,使用空接口直接进行相等比较,可以大大简化代码量,方便后期维护。

Archives