色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

struct,slice,map是否相等以及幾種對(duì)比方法的區(qū)別

馬哥Linux運(yùn)維 ? 來(lái)源:稀土掘金 ? 2024-01-08 18:20 ? 次閱讀

一、前言

對(duì)比兩個(gè)struct或者map,slice是否相等是大家經(jīng)常會(huì)有的需求,想必大家也都接觸過(guò)很多對(duì)比的方式,比如==,reflect.DeepEqual(),cmp.Equal()等。

這么多種對(duì)比方式,適用場(chǎng)景和優(yōu)缺點(diǎn)都有哪些呢?為什么可以用==,有的卻不可以呢?除了這三個(gè),還有其他的方式可以判斷相等嗎?問(wèn)題多多,且一起研究研究。

二、== 的對(duì)比方式

1、golang的四大類型

golang中的數(shù)據(jù)類型可以分為以下 4 大類:


基本類型:整型(
int/uint/int8/uint8/int16/uint16/int32/uint32/int64/uint64/byte/rune等)、浮點(diǎn)數(shù)(
float32/float64)、復(fù)數(shù)類型(
complex64/complex128)、字符串(
string)。
復(fù)合類型(又叫聚合類型):數(shù)組和結(jié)構(gòu)體類型。
引用類型:切片(slice)、map、channel、指針。
接口類型:如error :類型一致且是基本類型,值相等的時(shí)候,才能==,非基本類型會(huì)panic panic: runtime er
ror: comparing uncomparable type []int

2、== 適用的類型

我們?nèi)粘i_(kāi)發(fā)中,經(jīng)常見(jiàn)到使用==的類型一般是:string,int等基本類型。struct有時(shí)候可以用有時(shí)候不可以。slice和map使用 ==會(huì)報(bào)錯(cuò).


int1:=10
int2:=10
str1:="11"
str2:="11"
if int1 == int2{}
if str1 == str2{}

int和string是值類型,我們直接對(duì)比他們的值。當(dāng)然,前提是類型要一致,類型不一致編譯過(guò)不了。

3、slice和map使用 ==

首先golang里面有種說(shuō)法:


切片之間不允許比較。切片只能與nil值比較。
map之間不允許比較。map只能與nil值比較。

那么我們分別測(cè)試下發(fā)現(xiàn):


(1)map比較會(huì)報(bào)錯(cuò):map can only be compared to nil
(2)切片報(bào)錯(cuò):the operator == is not defined on []int64
    slice can only be compared to nil

(1)那么兩個(gè)nil是否可以==比較呢

答案是不能:invalid operation: nil == nil (operator == not defined on nil)

(2)slice,map使用==的場(chǎng)景

就像上面說(shuō)的,slice和map只能和nil使用==,他們各自之間是不可以的。


s1 := []int64{1, 2}
if s1 == nil {} //編輯器不會(huì)提示報(bào)錯(cuò)

(3)為什么slice和map不可以

因?yàn)閟lice和map不止是需要比較值,還需要比較len和cap,層級(jí)比較深的話還需要遞歸比較,不是簡(jiǎn)單的==就可以比較的,具體的我們可以參照reflect.DeepEqual()中實(shí)現(xiàn)的切片對(duì)比代碼。另外有大佬也說(shuō)會(huì)出現(xiàn)循環(huán)引用的問(wèn)題。

4、channel使用 ==

channel是引用類型,對(duì)比的是存儲(chǔ)數(shù)據(jù)的地址。channel是可以使用==的,只要類型一樣就可以。


ch1 := make(chan int, 1)
ch2 := ch1
if cha2 == cha1{fmt.Println("true")}

5、struct結(jié)構(gòu)體使用==

(1)首先要明確幾點(diǎn):


1)結(jié)構(gòu)體的定義只是一種內(nèi)存布局的描述,只有當(dāng)結(jié)構(gòu)體實(shí)例化時(shí),才會(huì)真正地分配內(nèi)存。
實(shí)例化就是根據(jù)結(jié)構(gòu)體定義的格式創(chuàng)建一份與格式一致的內(nèi)存區(qū)域,結(jié)構(gòu)體實(shí)例與實(shí)例間的
內(nèi)存是完全獨(dú)立的
2)對(duì)結(jié)構(gòu)體進(jìn)行&取地址操作時(shí),視為對(duì)該類型進(jìn)行一次 new 的實(shí)例化操作
因此:go中的結(jié)構(gòu)體: v = Struct {}, v = &Struct{} 這個(gè)兩種寫法是等價(jià)的

結(jié)構(gòu)體這里比較復(fù)雜一些。我們可以先下結(jié)論:

1、簡(jiǎn)單結(jié)構(gòu)的結(jié)構(gòu)體,里面都是值類型或者指針的話,是可以使用 ==的
2、結(jié)構(gòu)體中含有slice或者map,都是不可以用==

(2)簡(jiǎn)單結(jié)構(gòu)體的==


type Value struct {
    Name   string
    Gender string
    }
 
    func main() {
        v1 := Value{Name: "test", Gender: "男"}
        v2 := Value{Name: "test", Gender: "男"}
        if v1 == v2 {
            fmt.Println("true")
            return
        }
    }

(3)帶指針的結(jié)構(gòu)體==

    首先要明確,指針類型指向的地址不一樣,肯定是沒(méi)辦法比較的,如果地址一樣,那么也可以用==
    首先要明確,指針類型指向的地址不一樣,肯定是沒(méi)辦法比較的,如果地址一樣,那么也可以用==
    type Value struct {
    Name   string
    Gender *string
    }
 
    func main() {
         Gender :=new(string) //下面賦值用的同一個(gè)變量,地址相同
        v1 := Value{Name: "test", Gender: Gender}
        v2 := Value{Name: "test", Gender: Gender}
        if v1 == v2 {
            fmt.Println("true")
            return
        }
    }


(4)強(qiáng)制轉(zhuǎn)換類型的==


type StructA struct {
    Name string
    }
 
    type StructB struct {
        Name string
    }
 
    func main() {
        s1 := StructA{Name: "test1"}
        s2 := StructB{Name: "test1"}
        if s1 == StructA(s2) {
            fmt.Println("true")
            return
        }    
   }

那復(fù)雜類型的結(jié)構(gòu)體呢,要如何對(duì)比相等?包括slice和map如何對(duì)比相等呢?接下里就引入其他的對(duì)比方式。

三、reflect.DeepEqual() 和cmp.Equal()

1、reflect.DeepEqual()

reflect包提供的深度對(duì)比(遞歸)的方法,適用于go中的slice,map,struct,function的對(duì)比。

(1)對(duì)比規(guī)則


    相同類型的值是深度相等的,不同類型的值永遠(yuǎn)不會(huì)深度相等。
    當(dāng)數(shù)組值(array)的對(duì)應(yīng)元素深度相等時(shí),數(shù)組值是深度相等的。
    當(dāng)結(jié)構(gòu)體(struct)值如果其對(duì)應(yīng)的字段(包括導(dǎo)出和未導(dǎo)出的字段)都是深度相等的,則該值是深度相等的。
    當(dāng)函數(shù)(func)值如果都是零,則是深度相等;否則就不是深度相等。
    當(dāng)接口(interface)值如果持有深度相等的具體值,則深度相等。
    當(dāng)切片(slice)序號(hào)相同,如果值,指針都相等,那么就是深度相等的
    當(dāng)哈希表(map)相同的key,如果值,指針都相等,那么就是深度相等的。

(2)對(duì)比實(shí)例

通過(guò)規(guī)則可以知道,reflect.DeepEqual是可以比較struct的,同時(shí)也可以用來(lái)比較slice和map。
     func main() {
        s1 := StructA{Name: "test", Hobby: []string{"唱", "跳"}}
        s2 := StructA{Name: "test", Hobby: []string{"唱", "跳"}}
        if reflect.DeepEqual(s1, s2) {
            fmt.Println("struct true")
        }
        mp1 := map[int]int{1: 10, 2: 20}
  mp2 := map[int]int{1: 10, 2: 20}
         if ok := reflect.DeepEqual(mp1, mp2);ok {
    fmt.Println("mp1 == mp2!")
      } else {
    fmt.Println("mp1 != mp2!")
      }
    }
  

2、cmp.Equal()

go-cmp是Google開(kāi)源的比較庫(kù),它提供了豐富的選項(xiàng)。

這個(gè)包旨在成為reflect.DeepEqual比較兩個(gè)值在語(yǔ)義上是否相等的更強(qiáng)大和更安全的替代方案。

參考:在測(cè)試中使用go-cmp

(1)對(duì)比規(guī)則:


1.在經(jīng)過(guò)路徑過(guò)濾,值過(guò)濾和類型過(guò)濾之后,會(huì)生一些忽略、轉(zhuǎn)換、比較選項(xiàng),如果選項(xiàng)中存在忽略,
則忽略比較,如果轉(zhuǎn)換器比較器的數(shù)據(jù)大于1,則會(huì)panic(因?yàn)楸容^操作不明確)。如果選項(xiàng)中
存在轉(zhuǎn)換器,則調(diào)用轉(zhuǎn)換器轉(zhuǎn)換當(dāng)前值,再遞歸調(diào)用轉(zhuǎn)換器輸出類型的Equal。如果包含一個(gè)比較器。
則比較使用比較器比較當(dāng)前值。否則進(jìn)入下一比較階段。


2.如果比較值有一個(gè)(T) Equal(T) bool 或者 (T) Equal(I) bool,那么,即使x與y是nil,
也會(huì)調(diào)用x.Equal(y)做為結(jié)果。如果不存在這樣的方法,則進(jìn)入下一階段。


3.在最后階段,Equal方法嘗試比較x與y的基本類型。使用go語(yǔ)言的 == 比較基本類型
(bool, intX, float32,float64, complex32,complex64, string, chan)。


4.在比較struct時(shí),將遞歸的比較struct的字段。如果結(jié)構(gòu)體包含未導(dǎo)出的字段,函數(shù)會(huì)panic。
可以通過(guò)指定cmpopts.IgnoreUnexported來(lái)忽略未導(dǎo)出的字段,也可以使用
cmp.AllowUnexported來(lái)指定比較未導(dǎo)出的字段。

(2)代碼


// 傳入要對(duì)比的結(jié)構(gòu)即可
func Equal(x, y interface{}, opts ...Option) bool {
  s := newState(opts)
  s.compareAny(rootStep(x, y))
  return s.result.Equal()
}


//獲取diff差異
func Diff(x, y interface{}, opts ...Option) string {
}


3、cmp和DeepEqual的區(qū)別?


安全:cmp.Equal()函數(shù)不會(huì)比較未導(dǎo)出字段(即字段名首字母小寫的字段)。遇到未導(dǎo)出字段,
cmp.Equal()直接panic,reflect.DeepEqual()會(huì)比較未導(dǎo)出的字段。


強(qiáng)大:cmp.Equal()函數(shù)提供豐富的函數(shù)參數(shù),讓我們可以實(shí)現(xiàn):忽略部分字段,比較零值,
轉(zhuǎn)換某些值,允許誤差等。


共同點(diǎn):兩種比較類型,都會(huì)比較:對(duì)象類型,值,指針地址等。切片會(huì)按照索引比較值,
map是按照key相等比較值

四、其他對(duì)比方式

1、testify庫(kù)的 assert.Equal()

參考:Go 每日一庫(kù)之 testify

我們?cè)趯憜螠y(cè)的時(shí)候,經(jīng)常會(huì)使用assert.Equal()來(lái)做對(duì)比,原理如下:

(1)[]byte類型就使用bytes.Equal()
(2)非[]byte類型,使用reflect.DeepEqual()
(3)不相等則獲取diff

2、bytes.Equal()

標(biāo)準(zhǔn)庫(kù)中針對(duì)特定類型進(jìn)行比較相等性的函數(shù)或方法。例如:想比較兩個(gè)byte slice就可以使用bytes.Compare函數(shù)。

reflect.DeepEqual()函數(shù)在比對(duì)slice的時(shí)候,如果發(fā)現(xiàn)是uint8類型,也就是[]byte類型,也會(huì)調(diào)用bytes包的對(duì)比方法


case Slice:
        // Special case for []byte, which is common.
        if v1.Type().Elem().Kind() == Uint8 {
         return bytealg.Equal(v1.Bytes(), v2.Bytes())
        }
        //轉(zhuǎn)化為string之間的對(duì)比
        func Equal(a, b []byte) bool {
         return string(a) == string(b)
        }


五、效率對(duì)比及總結(jié)

1、效率對(duì)比

效率對(duì)比參考:Golang幾種對(duì)象比較方法

1、簡(jiǎn)單類型的==對(duì)比速度最快
2、復(fù)雜類型,自己知道結(jié)構(gòu)之后寫的自定義對(duì)比速度次之
3、復(fù)雜結(jié)構(gòu)且不確定結(jié)構(gòu)的,使用cmp.Equal()或者reflect.DeepEqual()都可以,就是效率低點(diǎn)
4、assert.Equal()底層使用的就是reflect.DeepEqual()

2、總結(jié)

我們發(fā)現(xiàn)對(duì)比的兩個(gè)結(jié)構(gòu)是否相等,方式很多,效率也有高有低。選擇合適自己需求的最重要。相對(duì)來(lái)說(shuō),cmp包是要更安全且可操作性更強(qiáng)一點(diǎn),主要是看大家的喜好了。

鏈接:https://juejin.cn/post/7316450414158200847






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 轉(zhuǎn)換器
    +關(guān)注

    關(guān)注

    27

    文章

    8694

    瀏覽量

    147091
  • 比較器
    +關(guān)注

    關(guān)注

    14

    文章

    1650

    瀏覽量

    107185
  • 存儲(chǔ)數(shù)據(jù)

    關(guān)注

    0

    文章

    88

    瀏覽量

    14100

原文標(biāo)題:golang中如何比較struct,slice,map是否相等以及幾種對(duì)比方法的區(qū)別

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    請(qǐng)教Xilinx Slice使用的問(wèn)題

    在使用ISE進(jìn)行實(shí)現(xiàn)過(guò)程中,占用slice的資源較多,如圖中所示,想用unrelated logic部分,期望能夠?qū)?b class='flag-5'>slice資源均衡使用,而折騰了好久,改了好多綜合、map等的設(shè)置,可都
    發(fā)表于 02-28 14:55

    是否有指示MAP方法

    寄存器上的SRL。是否有指示MAP方法,它不應(yīng)該在某些信號(hào)上推斷SRL?謝謝杰夫以上來(lái)自于谷歌翻譯以下為原文I have a design that has high clock rates.I
    發(fā)表于 10-10 10:52

    labview中二值化結(jié)果顯示的幾種方式對(duì)比

    不同的顏色顯示到image上。對(duì)比方法②和方法③的效果一樣,但是方法②更簡(jiǎn)便,推薦使用方法②龍哥手把手教您LabVIEW視覺(jué)設(shè)計(jì)課程火熱上線!!詳情可點(diǎn)擊下方鏈接進(jìn)行查看:http:/
    發(fā)表于 08-16 18:19

    XILINX MIG(DDR3) IP的AXI接口與APP接口的區(qū)別以及優(yōu)缺點(diǎn)對(duì)比

    XILINX MIG(DDR3) IP的AXI接口與APP接口的區(qū)別以及優(yōu)缺點(diǎn)對(duì)比
    發(fā)表于 11-24 21:47

    Delphi中比較GUID是否相等

    Delphi中比較GUID是否相等,CompareMem(@guid1, @guid2, SizeOf(TGUID)),最開(kāi)始時(shí)想到的方法
    發(fā)表于 06-22 10:11 ?1707次閱讀

    幾種芯片的對(duì)比

    幾種芯片的對(duì)比,,希望有幫助對(duì)大家
    發(fā)表于 01-20 17:31 ?2次下載

    幾種步進(jìn)電機(jī)加減速方法對(duì)比研究及其應(yīng)用

    幾種步進(jìn)電機(jī)加減速方法對(duì)比研究及其應(yīng)用。
    發(fā)表于 05-03 11:44 ?12次下載

    typedef struct的用法

    typedef是類型定義的意思。typedef struct 是為了使用這個(gè)結(jié)構(gòu)體方便。具體區(qū)別在于:若struct node{ }這樣來(lái)定義結(jié)構(gòu)體的話。在定義 node 的結(jié)構(gòu)體變量時(shí),需要這樣寫:
    發(fā)表于 11-09 17:20 ?3375次閱讀

    Java Map幾種循環(huán)方式學(xué)習(xí)總結(jié)

    本文檔內(nèi)容介紹了基于Java Map幾種循環(huán)方式學(xué)習(xí)總結(jié),供參考
    發(fā)表于 03-19 15:51 ?0次下載

    分析對(duì)比幾種常用軸修復(fù)方法

    分析對(duì)比幾種常用軸修復(fù)方法
    發(fā)表于 12-02 11:05 ?1次下載

    C++中struct和class的區(qū)別

    C++中struct和class的區(qū)別是什么?C++中struct和class的最大區(qū)別在于: ? ? ? ? struct的成員默認(rèn)是公有
    的頭像 發(fā)表于 03-10 17:41 ?758次閱讀

    PostgreSQL準(zhǔn)確且快速的數(shù)據(jù)對(duì)比方法

    NineData 數(shù)據(jù)對(duì)比是一款云原生數(shù)據(jù)對(duì)比產(chǎn)品,具備每秒處理 100 萬(wàn)筆記錄的高效能力。它提供了一站式支持,適用于 IDC 自建、云主機(jī)自建以及云數(shù)據(jù)庫(kù)。NineData 支持多種數(shù)據(jù)庫(kù),包括
    的頭像 發(fā)表于 09-12 15:46 ?999次閱讀
    PostgreSQL準(zhǔn)確且快速的數(shù)據(jù)<b class='flag-5'>對(duì)比方法</b>

    List 轉(zhuǎn) Map方法

    ; // 構(gòu)造函數(shù) 、 get 、 set } 我們假定 id 字段 是唯一的, 所以我們把 id 作為 Map 的key。 使用 Java 8 之前的方法 在使用Java 8 之前,就只能使用比
    的頭像 發(fā)表于 10-09 16:10 ?1620次閱讀

    typedef struct和直接struct區(qū)別

    在C語(yǔ)言中, typedef 和 struct 是兩種不同的關(guān)鍵字,它們?cè)诙x和使用上有著明顯的區(qū)別。 typedef struct 和直接 struct 在 C 語(yǔ)言中用于定義結(jié)構(gòu)體
    的頭像 發(fā)表于 08-20 10:58 ?2716次閱讀

    typedef和struct有啥區(qū)別

    在C語(yǔ)言中, typedef 和 struct 是兩個(gè)非常重要的關(guān)鍵字,它們?cè)诙x數(shù)據(jù)結(jié)構(gòu)時(shí)扮演著關(guān)鍵的角色。然而,它們之間有一些明顯的區(qū)別。 1. struct 關(guān)鍵字 struct
    的頭像 發(fā)表于 08-20 11:00 ?1152次閱讀
    主站蜘蛛池模板: 久久青青草视频在线观| www.99在线| 小寡妇好紧进去了好大看视频| 久久中文字幕人妻AV熟女| 阿片在线播放| 伊在香蕉国产在线视频| 日韩精品无码久久一区二区三| 97人妻在线公开视频在线观看| 亚洲国产高清在线观看视频| 青青久久网| 免费在线观看的毛片| 国产揄拍国产精品| 国产99久久亚洲综合精品西瓜tv | china中国gay偷拍| 伊人第一路线| 亚洲日韩KKK444KKK聚色| 色中色成人论坛| 欧美另类一区| 久久亚洲一级α片| 黄色网址在线播放| 工口肉肉彩色不遮挡| 被黑人群jian又粗又大H| 55夜色66夜亚洲精品播放| 亚洲免费在线播放| 亚洲AV蜜桃永久无码精品红樱桃 | 国产日韩精品SUV| 国产精品人妻99一区二| 大胸美女被cao哭| 被送到黑人性奴俱乐部| 99久久亚洲| gay台湾无套男同志xnxⅹ| 97在线播放视频| 国产午夜视频在线| 国产精品成人在线播放| 俄罗斯老妇女BBXX| 父皇轻点插好疼H限| 大香交伊人| 国产精品久久婷婷五月色| 国产高清美女一级毛片久久| 国产成人精品视频频| 成年黄网站免费大全毛片|