最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang判斷struct/slice/map是否相等以及對比的方法總結(jié)

 更新時間:2022年11月28日 17:06:30   作者:1個俗人  
平時開發(fā)中對比兩個struct或者map、slice是否相等是經(jīng)常遇到的,有很多對比的方式,比如==,reflect.DeepEqual(),cmp.Equal()等也是經(jīng)常容易混淆的,這么多種對比方式,適用場景和優(yōu)缺點都有哪些呢?今天我們來具體總結(jié)一下,感興趣的小伙伴們可以參考借鑒

前言

平時開發(fā)中對比兩個struct或者map、slice是否相等是經(jīng)常遇到的,有很多對比的方式,比如==reflect.DeepEqual(),cmp.Equal()等也是經(jīng)常容易混淆的,這么多種對比方式,適用場景和優(yōu)缺點都有哪些呢?為什么可以用==,有的卻不可以呢?問題多多,今天我們來具體總結(jié)一下,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

== 的對比方式

== 適用的類型

相信==判等操作,大家每天都在用。golang中對==的處理有一些細節(jié)的地方需要特別注意,==操作最重要的一個前提是:兩個操作數(shù)類型必須相同!如果類型不同,那么編譯時就會報錯。

示例代碼:

package main

import "fmt"

func main() {
    var a int32
    var b int64
    // 編譯錯誤:invalid operation a == b (mismatched types int32 and int64)
    fmt.Println(a == b)
}

經(jīng)常見到使用==的類型一般是:string,int等基本類型。struct有時候可以用有時候不可以。slicemap使用 ==會報錯。

slice和map使用 ==

因為slice和map不止是需要比較值,還需要比較len和cap,層級比較深的話還需要遞歸比較,不是簡單的==就可以比較的,所以他們各自之間是不可以直接用==比較的,slice和map只能和nil使用==。

  • 切片之間不允許比較。切片只能與nil值比較。
  • map之間不允許比較。map只能與nil值比較。
s1 := []int64{1, 3}
s2 := []int64{1, 2}
if s1 == nil {} //編輯器不會提示報錯
if s1 == s2 {} //編輯器會提示報錯

channel使用 ==

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

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

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

結(jié)構(gòu)體的定義只是一種內(nèi)存布局的描述,只有當結(jié)構(gòu)體實例化時,才會真正地分配內(nèi)存。

實例化就是根據(jù)結(jié)構(gòu)體定義的格式創(chuàng)建一份與格式一致的內(nèi)存區(qū)域,結(jié)構(gòu)體實例與實例間的

內(nèi)存是完全獨立的。對結(jié)構(gòu)體進行&取地址操作時,視為對該類型進行一次 new 的實例化操作

因此:go中的結(jié)構(gòu)體: v = Struct {}, v = &Struct{} 這個兩種寫法是等價的。

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

示例代碼:

package main

import (
    "fmt" 
)
type User struct {
    Name string
    Age  int64
}
type People struct {
    Name string
    Hobby []string
}

func main() {
        p1 := People{Name: "test", Hobby: []string{"唱", "跳"}}
        p2 := People{Name: "test", Hobby: []string{"唱", "跳"}}

        u1 := User{Name: "test", Age:18}
		u2 := User{Name: "test", Age:18}

        if p1 == p2 {
            fmt.Println("p1 ==  p2") //報錯
        }

    	if u1 == u2 {
            fmt.Println("u1 ==  u2")
        }
    }

reflect.DeepEqual() 和cmp.Equal()

reflect.DeepEqual()

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

對比規(guī)則

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

通過以上規(guī)則可以看到,reflect.DeepEqual是可以比較struct的,同時也可以用來比較slicemap。

示例代碼:

package main

import (
    "fmt"
    "reflect"
)

type People struct {
    Name string
    Hobby []string
}

func main() {
        p1 := People{Name: "test", Hobby: []string{"唱", "跳"}}
        p2 := People{Name: "test", Hobby: []string{"唱", "跳"}}
        if reflect.DeepEqual(p1, p2) {
            fmt.Println("struct true")
        }
        mp1 := map[int]int{1: 1, 2: 2}
	    mp2 := map[int]int{1: 1, 2: 2}
        if ok := reflect.DeepEqual(mp1, mp2);ok {
			fmt.Println("mp1 == mp2!")
	    } else {
			fmt.Println("mp1 != mp2!")
	    }
    }

cmp.Equal()

go-cmp是 Google 開源的比較庫,它提供了豐富的選項。

對比規(guī)則

  • 在經(jīng)過路徑過濾,值過濾和類型過濾之后,會生一些忽略、轉(zhuǎn)換、比較選項,如果選項中存在忽略,則忽略比較,如果轉(zhuǎn)換器和比較器的數(shù)據(jù)大于1,則會panic(因為比較操作不明確)。如果選項中存在轉(zhuǎn)換器,則調(diào)用轉(zhuǎn)換器轉(zhuǎn)換當前值,再遞歸調(diào)用轉(zhuǎn)換器輸出類型的Equal。如果包含一個比較器。則比較使用比較器比較當前值。否則進入下一比較階段。
  • 如果比較值有一個(T) Equal(T) bool 或者 (T) Equal(I) bool,那么,即使x與y是nil,也會調(diào)用x.Equal(y)做為結(jié)果。如果不存在這樣的方法,則進入下一階段。
  • 在最后階段,Equal方法嘗試比較x與y的基本類型。使用go語言的 == 比較基本類型(bool, intX, float32,float64, complex32,complex64, string, chan)。
  • 在比較struct時,將遞歸的比較struct的字段。如果結(jié)構(gòu)體包含未導(dǎo)出的字段,函數(shù)會panic可以通過指定cmpopts.IgnoreUnexported來忽略未導(dǎo)出的字段,也可以使用cmp.AllowUnexported來指定比較未導(dǎo)出的字段。

示例代碼:

package main

import (
  "fmt"

  "github.com/google/go-cmp/cmp"
)

type Contact struct {
  Phone string
  Email string
}

type User struct {
  Name    string
  Age     int
  Contact *Contact
}

func main() {
  u1 := User{Name: "test", Age: 18}
  u2 := User{Name: "test", Age: 18}

  fmt.Println("u1 == u2?", u1 == u2)  //true
  fmt.Println("u1 equals u2?", cmp.Equal(u1, u2)) //true

  c1 := &Contact{Phone: "123456789", Email: "dj@example.com"}
  c2 := &Contact{Phone: "123456789", Email: "dj@example.com"}

  u1.Contact = c1
  u2.Contact = c1
  fmt.Println("u1 == u2 with same pointer?", u1 == u2) //true
  fmt.Println("u1 equals u2 with same pointer?", cmp.Equal(u1, u2)) //true

  u2.Contact = c2
  fmt.Println("u1 == u2 with different pointer?", u1 == u2) //false 
  fmt.Println("u1 equals u2 with different pointer?", cmp.Equal(u1, u2)) //true
}

cmp和DeepEqual的區(qū)別

  • 安全:cmp.Equal()函數(shù)不會比較未導(dǎo)出字段(即字段名首字母小寫的字段)。遇到未導(dǎo)出字段,cmp.Equal()直接panic,reflect.DeepEqual()會比較未導(dǎo)出的字段。
  • 強大:cmp.Equal()函數(shù)提供豐富的函數(shù)參數(shù),讓我們可以實現(xiàn):忽略部分字段,比較零值,轉(zhuǎn)換某些值,允許誤差等。
  • 共同點:兩種比較類型,都會比較:對象類型,值,指針地址等。切片會按照索引比較值,map是按照key相等比較值。

性能比較

簡單類型的==對比速度最快

復(fù)雜類型,自己知道結(jié)構(gòu)之后寫的自定義對比速度次之

復(fù)雜結(jié)構(gòu)且不確定結(jié)構(gòu)的,使用cmp.Equal()或者reflect.DeepEqual()都可以,就是效率低點

assert.Equal()底層使用的就是reflect.DeepEqual()

總結(jié)

對于比較兩個struct或者map,slice是否相等,方式很多,效率也有差異。選擇合適自己需求的最重要。相對來說,cmp包是要更安全且可操作性更強一點。

到此這篇關(guān)于Golang判斷struct/slice/map是否相等以及對比的方法總結(jié)的文章就介紹到這了,更多相關(guān)Golang struct slice map內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一文初探?Goroutine?與?channel基本用法

    一文初探?Goroutine?與?channel基本用法

    這篇文章主要為大家介紹了一文初探?Goroutine?與?channel基本用法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • go?REST?API設(shè)計模式和反模式示例解析

    go?REST?API設(shè)計模式和反模式示例解析

    在這篇文章中,我們將探討一些常見的REST?API設(shè)計模式和開發(fā)者應(yīng)該注意的反模式,我們還將提供Golang和Open?API?Schema的代碼片段來幫助說明這些概念,有需要的朋友可以借鑒參考下
    2023-09-09
  • Go定時器cron的使用詳解

    Go定時器cron的使用詳解

    本篇文章主要介紹了Go定時器cron的使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • Go并發(fā)編程實踐

    Go并發(fā)編程實踐

    并發(fā)編程一直是Golang區(qū)別與其他語言的很大優(yōu)勢,也是實際工作場景中經(jīng)常遇到的。近日筆者在組內(nèi)分享了我們常見的并發(fā)場景,及代碼示例,以期望大家能在遇到相同場景下,能快速的想到解決方案,或者是拿這些方案與自己實現(xiàn)的比較,取長補短。現(xiàn)整理出來與大家共享
    2017-01-01
  • 從入門到精通:Go語言XML數(shù)據(jù)解析指南

    從入門到精通:Go語言XML數(shù)據(jù)解析指南

    Go語言的XML包提供了強大的數(shù)據(jù)解析功能,讓你輕松處理各種XML格式的數(shù)據(jù),這個指南將帶你深入了解如何使用Go語言的XML包,快速上手XML數(shù)據(jù)解析,準備好開啟XML解析之旅了嗎?Let's?Go!
    2024-03-03
  • go版tensorflow安裝教程詳解

    go版tensorflow安裝教程詳解

    這篇文章主要介紹了go版tensorflow安裝教程詳解,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • GO項目配置與使用的方法步驟

    GO項目配置與使用的方法步驟

    本文主要介紹了GO項目配置與使用的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧<BR>
    2022-06-06
  • golang Gorm與數(shù)據(jù)庫完整性約束詳解

    golang Gorm與數(shù)據(jù)庫完整性約束詳解

    這篇文章主要介紹了golang Gorm與數(shù)據(jù)庫完整性約束詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • golang defer執(zhí)行順序全面詳解

    golang defer執(zhí)行順序全面詳解

    這篇文章主要為大家介紹了golang defer執(zhí)行順序全面詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • golang(gin)的全局統(tǒng)一異常處理方式,并統(tǒng)一返回json

    golang(gin)的全局統(tǒng)一異常處理方式,并統(tǒng)一返回json

    這篇文章主要介紹了golang(gin)的全局統(tǒng)一異常處理方式,并統(tǒng)一返回json,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01

最新評論

双鸭山市| 资讯 | 黎城县| 长寿区| 平舆县| 江口县| 铜梁县| 余庆县| 永城市| 双鸭山市| 泊头市| 镶黄旗| 博白县| 安丘市| 河西区| 大新县| 弥渡县| 平湖市| 元阳县| 克什克腾旗| 灌阳县| 化德县| 汾阳市| 嘉善县| 祁门县| 常山县| 淮安市| 博野县| 奈曼旗| 二连浩特市| 万盛区| 盐池县| 长寿区| 高密市| 教育| 泗阳县| 武宣县| 兴山县| 抚远县| 屏东市| 昆明市|