使用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等类型。
总结,使用空接口直接进行相等比较,可以大大简化代码量,方便后期维护。