❝「第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 } 複製代碼
上面就是今天要跟你們分享的內容,有什麼問題歡迎你們在後臺給大叔留言,關注大叔說碼,咱們下期見~
參考文檔: