前言
判断结构体是否为空不能用nil
reflect.DeepEqual本质上是递归,使用反射类型测试深度相等性,可以比较任意两个go语言变量是否相等
type Person struct {
Id int
Name string
}
func main() {
p := Person{}
fmt.Println(p == (Person{})) //true
fmt.Println(reflect.DeepEqual(p, Person{})) //true
ptr := &Person{}
fmt.Println(ptr == nil) //false
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, m2)) //true
arr1 := []int{1, 2, 3, 4, 5}
arr2 := []int{5, 4, 3, 2, 1}
fmt.Println(reflect.DeepEqual(arr1, arr2)) //false
arr3 := []int{1, 2, 3, 4, 5}
fmt.Println(reflect.DeepEqual(arr1, arr3)) //true
}
疑问
reflect.DeepEqual源码中有个packEface方法很是神奇,变量e是emptyInterface指针类型,对e的属性赋值后,变量i居然获取到了外部变量的属性值(eg:p.Id,p.Name的值),功力不够目前没明白
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
typ *rtype
word unsafe.Pointer
}
// Value is the reflection interface to a Go value.
type Value struct {
typ *rtype
ptr unsafe.Pointer
flag
}
// packEface converts v to the empty interface.
func packEface(v Value) interface{} {
t := v.typ
var i interface{}
e := (*emptyInterface)(unsafe.Pointer(&i))
// First, fill in the data portion of the interface.
switch {
case ifaceIndir(t):
if v.flag&flagIndir == 0 {
panic("bad indir")
}
// Value is indirect, and so is the interface we're making.
ptr := v.ptr
if v.flag&flagAddr != 0 {
// TODO: pass safe boolean from valueInterface so
// we don't need to copy if safe==true?
c := unsafe_New(t)
typedmemmove(t, c, ptr)
ptr = c
}
e.word = ptr
case v.flag&flagIndir != 0:
// Value is indirect, but interface is direct. We need
// to load the data at v.ptr into the interface data word.
e.word = *(*unsafe.Pointer)(v.ptr)
default:
// Value is direct, and so is the interface.
e.word = v.ptr
}
// Now, fill in the type portion. We're very careful here not
// to have any operation between the e.word and e.typ assignments
// that would let the garbage collector observe the partially-built
// interface value.
e.typ = t
return i
}