Golang數(shù)據(jù)類型比較詳解
直接使用==比較的情況
分類 | 說明 | 是否能比較 | 說明 |
---|---|---|---|
基本類型 | 整型( int/uint/int8/uint8/int16/uint16/int32/uint32/int64/uint64/byte/rune等)浮點(diǎn)數(shù)( float32/float64)復(fù)數(shù)類型( complex64/complex128)字符串( string) | 是 | |
引用類型 | 切片(slice)、map | 否 | |
聚合類型(復(fù)合類型) | 數(shù)組 | 是 | 相同長度的數(shù)組可以比較,不同長度的數(shù)組不能進(jìn)行比較 |
結(jié)構(gòu)體 | 是 | 只包含可比較的類型情況下可比較 | |
接口類型 | 如error | 是 |
基本數(shù)據(jù)類
- 類型一致且是基本類型,值相等的時(shí)候,才能==
- 非基本類型會panic panic: runtime error: comparing uncomparable type []int
浮點(diǎn)比較
不過基本類型中也要注意浮點(diǎn)型的比較就不像我們現(xiàn)實(shí)中的一樣,比如0.1+0.2在計(jì)算中運(yùn)行結(jié)果就不是0.3了,而是0.30000000000000004了
package main import "fmt" func main() { var a float64=0.1 var b float64=0.2 // 0.30000000000000004 fmt.Println(a+b) }
字符串比較
一般的比較運(yùn)算符(==、!=、<、<=、>=、>)是通過在內(nèi)存中按字節(jié)比較來實(shí)現(xiàn)字符串比較的,因此比較的結(jié)果是字符串自然編碼的順序。字符串所占的字節(jié)長度可以通過函數(shù) len() 來獲取,例如 len(str)
比較兩個(gè)字符是否相等
package golangbase import ( "fmt" "testing" ) func TestString(t *testing.T) { str1 := "哈哈" str2 := "哈哈" fmt.Println(str1 == str2) }
輸出結(jié)果為true
引用類型
slice、map
- 切片之間不允許比較。切片只能與nil值比較
- map之間不允許比較。map只能與nil值比較
- 兩個(gè)nil也不能比較,會panic
slice、map比較
使用reflect.DeepEqual()
對比規(guī)則
- 相同類型的值是深度相等的,不同類型的值永遠(yuǎn)不會深度相等。
- 當(dāng)數(shù)組值(array)的對應(yīng)元素深度相等時(shí),數(shù)組值是深度相等的。
- 當(dāng)結(jié)構(gòu)體(struct)值如果其對應(yīng)的字段(包括導(dǎo)出和未導(dǎo)出的字段)都是深度相等的,則該值是深度相等的。
- 當(dāng)函數(shù)(func)值如果都是零,則是深度相等;否則就不是深度相等。
- 當(dāng)接口(interface)值如果持有深度相等的具體值,則深度相等。
- 當(dāng)切片(slice)序號相同,如果值,指針都相等,那么就是深度相等的
- 當(dāng)哈希表(map)相同的key,如果值,指針都相等,那么就是深度相等的。
使用示例
package golangbase import ( "reflect" "testing" ) type StructA struct { Name string Hobby []string } type StructB struct { Name string } func TestDeepEqual(t *testing.T) { s1 := StructA{Name: "test", Hobby: []string{"唱", "跳"}} s2 := StructA{Name: "test", Hobby: []string{"唱", "跳"}} println(reflect.DeepEqual(s1, s2))// true mp1 := map[int]int{1: 10, 2: 20} mp2 := map[int]int{1: 10, 2: 20} println(reflect.DeepEqual(mp1, mp2))// true }
channel、指針
指針可比較,只要指針指向的地址一樣,則相等
由于通過make創(chuàng)建channel后,返回的是一個(gè)指針,所以可以比較
c1 := make(chan int, 2) c2 := make(chan int, 2) c3 := c1 fmt.Println(c3 == c1) // true fmt.Println(c2 == c1) // false
聚合類型
數(shù)組
數(shù)組在go中是必須先確定長度的,也就是長度不能再去擴(kuò)容。并且它是個(gè)值拷貝,做參數(shù)傳到一個(gè)函數(shù)中被修改,那么外部的值還是一樣的不變的。Slice則相反。那么數(shù)組是否可以比較呢,看下面的例子:
package main import "fmt" func main() { a := [2]int{1, 2} b := [2]int{1, 2} c := [2]int{1, 3} d := [3]int{1, 2, 4} fmt.Println(a == b) // true fmt.Println(a == c) // false fmt.Println(a == d) // invalid operation: a == d (mismatched types [2]int and [3]int) }
可以看出,相同長度的數(shù)組是可以比較的,而不同長度的數(shù)組是不能進(jìn)行比較的。原因是什么呢?這是因?yàn)閿?shù)組類型中,數(shù)組的長度也是類型的一部分,不同長度的數(shù)組那么他們的類型也就被認(rèn)為不同的,所以無法比較
結(jié)構(gòu)體
只包含可比較的類型情況下可比較
package main import "fmt" type A struct { id int name string } func main() { a := A{id:5,name:"123"} b := A{id:5,name:"123"} c := A{id:5,name:"1234"} fmt.Println(a == b) // true fmt.Println(a == c) // false }
反例,因?yàn)閟lice不可比較,如果結(jié)構(gòu)體包含了slice,則不可比較
package main import "fmt" type A struct { id int name string son []int } func main() { a := A{id:5,name:"123",son:[]int{1,2,3}} b := A{id:5,name:"123",son:[]int{1,2,3}} fmt.Println(a == b) // invalid operation: a == b (struct containing []int cannot be compared) }
接口
Go 語言根據(jù)接口類型是否包含一組方法將接口類型分成了兩類:
- 使用 runtime.iface結(jié)構(gòu)體表示包含方法的接口
- 使用 runtime.eface結(jié)構(gòu)體表示不包含任何方法的 interface{} 類型
type eface struct { // 16 字節(jié) _type *_type data unsafe.Pointer } type iface struct { // 16 字節(jié) tab *itab data unsafe.Pointer }
一個(gè)接口值是由兩個(gè)部分組成的,即該接口對應(yīng)的類型和接口對應(yīng)具體的值
接口值的比較涉及這兩部分的比較,只有當(dāng)類型和值都相等(動(dòng)態(tài)值使用==比較),兩個(gè)接口值才是相等的??磦€(gè)例子:
var a interface{} = 0 var b interface{} = 2 var c interface{} = 0 var d interface{} = 0.0 fmt.Println(a == b) // false fmt.Println(a == c) // true fmt.Println(a == d) // false
a和c類型相同(都是int),值也相同(都是0,基本類型比較),故兩者相等。 a和b類型相同,值不等,故兩者不等。 a和d類型不同,a為int,d為float64,故兩者不等
最后做個(gè)練習(xí)
func TestJson(t *testing.T) { var x, y Data x = Data{ UUID: "856f5555806443e98b7ed04c5a9d6a9a", Content: 1, } bytes, _ := json.Marshal(x) _ = json.Unmarshal(bytes, &y) println(x) println(y) println(reflect.DeepEqual(x, y)) }
為什么結(jié)果為false?
debug看一下
原因是json.Unmarshal默認(rèn)會將所有的數(shù)字類型轉(zhuǎn)為float64
針對這種情況,可以封裝一個(gè)DeepEqual方法
func DeepEqual(v1, v2 interface{}) bool { if reflect.DeepEqual(v1, v2) { return true } bytesA, _ := json.Marshal(v1) bytesB, _ := json.Marshal(v2) return bytes.Equal(bytesA, bytesB) } 
以上就是Golang數(shù)據(jù)類型比較詳解的詳細(xì)內(nèi)容,更多關(guān)于Golang數(shù)據(jù)類型比較的資料請關(guān)注腳本之家其它相關(guān)文章!
- Go語言基礎(chǔ)語法和基本數(shù)據(jù)類型知識鞏固
- 夯實(shí)Golang基礎(chǔ)之?dāng)?shù)據(jù)類型梳理匯總
- 淺析Go常量為什么只支持基本數(shù)據(jù)類型
- Go語言數(shù)據(jù)類型簡單介紹
- 深入了解Golang中的數(shù)據(jù)類型
- Go語言中的基礎(chǔ)數(shù)據(jù)類型使用實(shí)例
- 重學(xué)Go語言之基礎(chǔ)數(shù)據(jù)類型詳解
- 淺析Go語言的數(shù)據(jù)類型及數(shù)組
- Go語言中基本數(shù)據(jù)類型的相互轉(zhuǎn)換詳解
- Go基本數(shù)據(jù)類型的具體使用
相關(guān)文章
Go返回int64類型字段超出javascript Number范圍的解決方法
這篇文章主要介紹了Go返回int64類型字段超出javascript Number范圍的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07SingleFlight模式的Go并發(fā)編程學(xué)習(xí)
這篇文章主要為大家介紹了SingleFlight模式的Go并發(fā)編程學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04Go語言標(biāo)準(zhǔn)庫sync.Once使用場景及性能優(yōu)化詳解
這篇文章主要為大家介紹了Go語言標(biāo)準(zhǔn)庫sync.Once使用場景及性能優(yōu)化詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12使用Golang搭建web服務(wù)的實(shí)現(xiàn)步驟
本文主要介紹了使用Golang搭建web服務(wù)的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04GoFrame框架garray并發(fā)安全數(shù)組使用開箱體驗(yàn)
這篇文章主要介紹了GoFrame框架garray并發(fā)安全數(shù)組使用開箱體驗(yàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06