詳解Go 語言中的比較操作符
這篇文章專注于 6 個(gè)操作符,==,!=,<,<=,> 和 >=。我們將深入探討它們的語法和用法的細(xì)微差別。對(duì)很多人來說,這聽起來不像是吸引人的事,或者他們可能已經(jīng)從其他編程語言獲得了糟糕的經(jīng)驗(yàn)。然而,在 Go 中它們定義的很好并簡(jiǎn)潔。下面討論的主題,如可比性將出現(xiàn)在其他場(chǎng)合,如 maps。為了使用上述操作符,至少有一個(gè)操作數(shù)需要可賦值給第二個(gè)操作數(shù):
package main import "fmt" type T struct { name string } func main() { s := struct{ name string }{"foo"} t := T{"foo"} fmt.Println(s == t) // true }
這條規(guī)則顯著縮小了可選范圍:
var a int = 1 var b rune = '1' fmt.Println(a == b)
類似的代碼在 Javascript 或 Python 中可以運(yùn)行。但在 Go 中它是非法的,并且在編譯時(shí)會(huì)被檢測(cè)到。
src/github.com/mlowicki/lab/lab.go:8: invalid operation: a == b (mismatched types int and rune)
可賦值不是唯一要求。這是相等和順序操作符的規(guī)則……
相等操作符
操作數(shù)需要使用 == 或 != 操作符進(jìn)行比較。哪些方法,哪些值可以被比較?Go 規(guī)范定義的非常明確:
boolean 值可比較(如果倆個(gè)值都是真或假,那么比較結(jié)果被認(rèn)為 true)
整數(shù)和浮點(diǎn)數(shù)比較:
var a int = 1 var b int = 2 var c float32 = 3.3 var d float32 = 4.4 fmt.Println(a == b) // false fmt.Println(c == d) // false
當(dāng)編譯時(shí) a == d 會(huì)拋出異常( int 和 float32 類型不匹配)因?yàn)樗豢赡苡?int 和 float 比較。
復(fù)數(shù)相等,如果他們的是實(shí)數(shù)和虛數(shù)部分都相等:
var a complex64 = 1 + 1i var b complex64 = 1 + 2i var c complex64 = 1 + 2i fmt.Println(a == b) // false fmt.Println(b == c) // true
字符串類型值可比較
指針類型值相等,如果他們都是 nil 或都指向相同的變量:
type T struct { name string } func main() { t1 := T{"foo"} t2 := T{"bar"} p1 := &t1 p2 := &t1 p3 := &t2 fmt.Println(p1 == p2) // true fmt.Println(p2 == p3) // false fmt.Println(p3 == nil) // false }
不同的 zero-size 變量可能具有相同的內(nèi)存地址,因此我們不假設(shè)任何指向這些變量的指針相等。
a1 := [0]int{} a2 := [0]int{} p1 := &a1 p2 := &a2 fmt.Println(p1 == p2) // might be true or false. Don't rely on it!
通道類型值相等,如果他們確實(shí)一樣(被相同的內(nèi)置 make 方法創(chuàng)建)或值都是 nil:
ch1 := make(chan int) ch2 := make(chan int) fmt.Println(ch1 == ch2) // false
接口類型是可比較。與通道和指針類型值比較一樣,如果是 nil 或 動(dòng)態(tài)類型和動(dòng)態(tài)值是相同的:
type I interface { m() } type J interface { m() } type T struct { name string } func (T) m() {} type U struct { name string } func (U) m() {} func main() { var i1, i2, i3, i4 I var j1 J i1 = T{"foo"} i2 = T{"foo"} i3 = T{"bar"} i4 = U{"foo"} fmt.Println(i1 == i2) // true fmt.Println(i1 == i3) // false fmt.Println(i1 == i4) // false fmt.Println(i1 == j1) // false }
比較接口類型的方法集不能相交。
接口類型 I 的 i 和 非接口類型 T 的 t 可比較,如果 T 實(shí)現(xiàn)了 I 則 T 類型的值是可比較的。如果 I 的 動(dòng)態(tài)類型和 T 是相同的,并且 i 的動(dòng)態(tài)值和 t 也是相同的,那么值是相等的:
type I interface { m() } type T struct{} func (T) m() {} type S struct{} func (S) m() {} func main() { t := T{} s := S{} var i I i = T{} fmt.Println(t == i) // true fmt.Println(s == i) // false } 結(jié)構(gòu)類型可比較,所以字段都需要比較。所有非空白字段相等則他們等。 a := struct { name string _ int32 }{name: "foo"} b := struct { name string _ int32 }{name: "foo"} fmt.Println(a == b) // true
Go 中 數(shù)組是同質(zhì)的 —— 只有同一類型(數(shù)組元素類型)的值可以被存儲(chǔ)其中。對(duì)于數(shù)組值比較,它們的元素類型需要可比較。如果對(duì)應(yīng)的元素相同,數(shù)組就相等。
就是這樣。上面列表很長(zhǎng)但并不充滿驚奇。嘗試了解它在 JavaScript 是如何工作的……
有三種類型不能比較 —— maps, slices 和 functions。Go 編譯器不允許這樣做,并且編譯比較 maps 的程序會(huì)引起一個(gè)錯(cuò)誤 map can only be compared to nil. 。展示的錯(cuò)誤告訴我們至少可以用 maps,slices 或 functions 和 nil 比較。
目前為止,我們知道接口值是可比較的,但 maps 是不可以的。如果接口值的動(dòng)態(tài)類型是相同的,但是不能比較(如 maps),它會(huì)引起一個(gè)運(yùn)行時(shí)錯(cuò)誤:
type T struct { meta map[string]string } func (T) m() {} func main() { var i1 I = T{} var i2 I = T{} fmt.Println(i1 == i2) } panic: runtime error: comparing uncomparable type main.T goroutine 1 [running]: panic(0x8f060, 0x4201a2030) /usr/local/go/src/runtime/panic.go:500 +0x1a1 main.main() ...
順序操作符
這些操作符只能應(yīng)用在三種類型:整數(shù),浮點(diǎn)數(shù)和字符串類型。這沒有什么特別的或 Go 特有的。值得注意的是字符串是按字典順序排列的。byte-wise 一次一個(gè)字節(jié)并沒有 Collation 算法。
fmt.Println("aaa" < "b") // true fmt.Println("ł" > "z") // true
結(jié)果
任何比較操作符的結(jié)果都是無類型布爾常量(true 或 false)。因?yàn)樗鼪]有類型,所以可以分配了給任何布爾變量:
var t T = true t = 3.3 < 5 fmt.Println(t)
這段代碼輸出 true。另一個(gè),嘗試分配 bool 類型的值:
var t T = true var b bool = true t = b fmt.Println(t)
產(chǎn)生一個(gè)錯(cuò)誤,不能使用 b (bool類型)分配給 T 類型。
總結(jié)
以上所述是小編給大家介紹的Go 語言中的比較操作符,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Go中調(diào)用JS代碼(otto)的實(shí)現(xiàn)示例
Otto是一個(gè)用Go語言實(shí)現(xiàn)的JavaScript解釋器,可用于執(zhí)行和操作JavaScript代碼,適合在Go項(xiàng)目中執(zhí)行簡(jiǎn)單的JS腳本,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-10-10Golang使用Docker進(jìn)行集成測(cè)試的示例詳解
集成測(cè)試需要解決外部依賴問題,如?MySQL、Redis、網(wǎng)絡(luò)等依賴,本文就來聊聊?Go?程序如何使用?Docker?來解決集成測(cè)試中外部依賴問題吧2023-07-07Go處理json數(shù)據(jù)方法詳解(Marshal,UnMarshal)
這篇文章主要介紹了Go處理json數(shù)據(jù)的方法詳解,Marshal(),UnMarshal(),需要的朋友可以參考下2022-04-04Windows系統(tǒng)中搭建Go語言開發(fā)環(huán)境圖文詳解
GoLand?是?JetBrains?公司推出的商業(yè)?Go?語言集成開發(fā)環(huán)境(IDE),這篇文章主要介紹了Windows系統(tǒng)中搭建Go語言開發(fā)環(huán)境詳解,需要的朋友可以參考下2022-10-10go slice 擴(kuò)容實(shí)現(xiàn)原理源碼解析
這篇文章主要為大家介紹了go slice 擴(kuò)容實(shí)現(xiàn)原理源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01