Go 里 interface 为什么能比较?到底在比什么?
这块其实是 Go 里面非常经典、非常容易懵的知识点。因为很多人看到fmt.Println(stu1stu2)// falsefmt.Println(stu3stu4)// true会想明明内容都是 Tom 为什么一个 false 一个 true真正原因在于interface 底层到底存了什么今天我们彻底讲清楚。一、先看代码typeStustruct{Namestring}typeStuIntinterface{}funcmain(){varstu1,stu2 StuIntStu{Tom},Stu{Tom}varstu3,stu4 StuIntStu{Tom},Stu{Tom}fmt.Println(stu1stu2)// falsefmt.Println(stu3stu4)// true}二、interface 底层到底是什么重点Go 里的 interface底层其实包含两个东西类型Type 值Value也就是interface (T, V)三、例如varxinterface{}123此时T int V 123四、再例如varxinterface{}hello此时T string V hello五、所以 interface 本质其实像一个盒子。盒子里装着值 这个值的类型六、interface 比较规则必须记住两个 interface 相等必须同时满足1. 类型相同T 相同2. 值相同V 相同七、也就是说(T1, V1) (T2, V2)必须T1 T2 并且 V1 V2八、现在分析 stu1 和 stu2重点代码varstu1,stu2 StuIntStu{Tom},Stu{Tom}九、这里放进去的是什么注意你写的是Stu{Tom}十、 是什么表示取地址得到指针十一、所以 interface 里装的是stu1T *Stu V 0x1000stu2T *Stu V 0x2000十二、为什么地址不同因为Stu{Tom}每次都会创建新的结构体对象内存地址自然不同。十三、真正底层发生了什么第一次Stu{Tom}可能在内存0x1000第二次Stu{Tom}可能在0x2000十四、虽然内容一样Name 都是 Tom但是指针地址不同十五、所以比较的是0x1000 0x2000结果false十六、真正核心重点指针比较比较的是地址不是内容十七、所以fmt.Println(stu1stu2)结果false十八、现在分析 stu3 和 stu4重点代码varstu3,stu4 StuIntStu{Tom},Stu{Tom}十九、这里和前面最大区别注意这里没有 所以放进去的不是指针。而是结构体值本身二十、所以 interface 里装的是stu3T Stu V Stu{Name:Tom}stu4T Stu V Stu{Name:Tom}二十一、现在比较什么比较结构体内容二十二、Go 结构体如何比较Go会逐字段比较。NameTom Tom成立。二十三、所以结果true二十四、真正核心区别必须理解指针 interface比较地址结构体 interface比较字段内容二十五、画图理解重点stu1interface ├── T *Stu └── V 0x1000stu2interface ├── T *Stu └── V 0x2000比较0x1000 ! 0x2000所以false二十六、再看 stu3interface ├── T Stu └── V {Name:Tom}stu4interface ├── T Stu └── V {Name:Tom}二十七、比较字段完全相同所以true二十八、为什么 interface 能直接 因为interface底层知道类型 值所以Go可以比较。二十九、但是有坑重点不是所有 interface 都能比较。三十、例如 slicevarainterface{}[]int{1,2}varbinterface{}[]int{1,2}fmt.Println(ab)三十一、会直接 panic因为slice 不可比较三十二、为什么 slice 不可比较因为slice底层包含指针 长度 容量Go不允许直接 。三十三、哪些类型可以比较可以intstringbool指针数组结构体字段都可比较不可以slicemapfunc三十四、所以 interface 比较还有个规则除了T 相同 V 相同还必须V 本身是可比较类型三十五、最经典 nil 坑超级重要例如varp*Stunilvarxinterface{}p三十六、此时 x 是 nil 吗很多新人会以为是 nil其实不是三十七、为什么因为interface 里其实是T *Stu V nil三十八、真正 nil interface必须T nil V nil三十九、所以fmt.Println(xnil)结果false四十、这个是 Go 面试超级经典题因为很多人不理解interface (T, V)四十一、最后一句总结必须记住interface 底层本质(Type, Value)两个 interface 相等必须类型相同 值相同指针比较比较地址结构体比较比较字段所以Stu{Tom}!Stu{Tom}因为两个不同地址而Stu{Tom}Stu{Tom}因为结构体字段完全相同