❝「第8期」 距离大叔的80期小目标还有72期,今天大叔要跟你们分享的依旧是golang的基础知识点——struct能不能比较,这个基础问题很考验你们基础和细节,也是面试官比较喜欢问的问题,接下来跟你们一块儿来了解一下吧。golang
❞
struct能不能比较? 很显然这句话包含了两种状况:web
在分析上面两个问题前,先跟你们梳理一下golang中,哪些数据类型是可比较的,哪些是不可比较的:面试
下面就跟你们分别分析一下上面两种状况吧数组
首先,咱们构造一个struct结构体来玩玩吧markdown
type S struct {
Name string Age int Address *int } func main() { a := S{ Name: "aa", Age: 1, Address: new(int), } b := S{ Name: "aa", Age: 1, Address: new(int), } fmt.Println(a == b) } 复制代码
运行上面的代码发现会打印false。既然能正常打印输出,说明是能够个比较的,接下来让咱们来个「死亡两问」app
什么能够比较?ide
回到上面的划重点部分,在总结中咱们能够知道,golang中 Slice,Map,Function 这三种数据类型是不能够直接比较的。咱们再看看S结构体,该结构体并无包含不可比较的成员变量,因此该结构体是能够直接比较的。函数
为何打印输出false?oop
a 和 b 虽然是同一个struct 的两个实例,可是由于其中的指针变量 Address 的值不一样,因此 a != b,若是a b 在初始化时把 Address 去掉(不给 Address 初始化),那么这时 a == b 为true, 由于ptr变量默认值是nil,又或者给 Address 成员变量赋上同一个指针变量的值,也是成立的。ui
若是给结构体S增长一个Slice类型的成员变量后又是什么状况呢?
type S struct {
Name string Age int Address *int Data []int } func main() { a := S{ Name: "aa", Age: 1, Address: new(int), Data: []int{1, 2, 3}, } b := S{ Name: "aa", Age: 1, Address: new(int), Data: []int{1, 2, 3}, } fmt.Println(a == b) } 复制代码
这时候会打印输出什么呢?true?false?实际上运行上面的代码会报下面的错误:
# command-line-arguments
./test.go:37:16: invalid operation: a == b (struct containing []int cannot be compared) 复制代码
a, b 虽然是同一个struct两个赋值相同的实例,由于结构体成员变量中带有了不能比较的成员(slice),是不能够直接用 == 比较的,因此只要写 == 就报错
「总结」
同一个struct的两个实例可比较也不可比较,当结构不包含不可直接比较成员变量时可直接比较,不然不可直接比较
但在平时的实践过程当中,当咱们须要对含有不可直接比较的数据类型的结构体实例进行比较时,是否是就无法比较了呢?事实上并不是如此,golang仍是友好滴,咱们能够借助 reflect.DeepEqual 函数 来对两个变量进行比较。因此上面代码咱们能够这样写:
type S struct {
Name string Age int Address *int Data []int } func main() { a := S{ Name: "aa", Age: 1, Address: new(int), Data: []int{1, 2, 3}, } b := S{ Name: "aa", Age: 1, Address: new(int), Data: []int{1, 2, 3}, } fmt.Println(reflect.DeepEqual(a, b)) } 复制代码
打印输出:
true
复制代码
那么 reflect.DeepEqual 是如何对变量进行比较的呢?
DeepEqual函数用来判断两个值是否深度一致。具体比较规则以下:
「结论」:能够比较,也不能够比较
可经过强制转换来比较:
type T2 struct {
Name string Age int Arr [2]bool ptr *int } type T3 struct { Name string Age int Arr [2]bool ptr *int } func main() { var ss1 T2 var ss2 T3 // Cannot use 'ss2' (type T3) as type T2 in assignment //ss1 = ss2 // 不一样结构体之间是不能够赋值的 ss3 := T2(ss2) fmt.Println(ss3==ss1) // true } 复制代码
若是成员变量中含有不可比较成员变量,即便能够强制转换,也不能够比较
type T2 struct {
Name string Age int Arr [2]bool ptr *int map1 map[string]string } type T3 struct { Name string Age int Arr [2]bool ptr *int map1 map[string]string } func main() { var ss1 T2 var ss2 T3 ss3 := T2(ss2) fmt.Println(ss3==ss1) // 含有不可比较成员变量 } 复制代码
编译报错:
# command-line-arguments
./test.go:28:18: invalid operation: ss3 == ss1 (struct containing map[string]string cannot be compared) 复制代码
struct必须是可比较的,才能做为key,不然编译时报错
type T1 struct {
Name string Age int Arr [2]bool ptr *int slice []int map1 map[string]string } type T2 struct { Name string Age int Arr [2]bool ptr *int } func main() { // n := make(map[T2]string, 0) // 无报错 // fmt.Print(n) // map[] m := make(map[T1]string, 0) fmt.Println(m) // invalid map key type T1 } 复制代码
上面就是今天要跟你们分享的内容,有什么问题欢迎你们在后台给大叔留言,关注大叔说码,咱们下期见~
参考文档: