您現在的位置是:首頁 > 遊戲
一道比較運算子相關的面試題把我虐的體無完膚
布林值怎麼比較
來自公眾號:新世界雜貨鋪
雜(貨鋪)談
今天這篇文章相對來說比較基礎,大家花幾分鐘時間看看,有所收穫自然是最好,沒有收穫也就消磨幾分鐘時間罷了,你不虧,筆者也不虧~
前幾期還是有一定難度的HTTP系列文章,今天卻是畫風突變講起了基礎,這當然是因為基礎重要呀。正所謂萬丈高樓平地起,我們夯實基礎,樓才能建的高,畢竟精美的小矮樓總是很容易被高樓遮擋。嗨,扯遠了,總之筆者今天寫這篇文章絕對不是下面這個原因:
累呀!真的累!工作嘛?當然不是!前幾期分析HTTP系列文章確實耗費了太多精力,週末連續熬夜就算是鐵打的人也扛不住,所以本週只有養精蓄銳這一個目的。
雜(貨鋪)言
Go中的比較運算子,你真的瞭解嗎?假如面試官問你下面輸出什麼,你的答案是什麼?
今天,筆者總結了一份比較運算子的相關文件,助力讀者夯實基礎(上述答案請參考後文)。
基本定理
在Go中,比較運算子也是遵循定理的, 兩條基本定理如下:
定理一
:相等運算子
==
和
!=
適用於具有可比性的運算元,排序運算子
<
,
<=
,
>
和
>=
適用於可排序的運算元。
定理二
:在任何比較中,至少滿足一個運算元能賦值給另一個運算元型別的變數。
常見型別的比較
常見型別的比較大家都懂,在這裡筆者就不詳細介紹了,僅列舉一下原則加深大家的印象:
布林值是可比較的,但不可排序,即僅適用於
==
和
!=
運算子。
整數和浮點數是可比較的且可排序,適用於所有比較運算子。
字串的值是可比較的,且按位元組排序,即比較時按位元組比較大小(不理解字串和位元組切片關係的,請參考深入理解go中字串這篇文章)。
以上即為常見型別的比較原則,下面我們結合例子逐步理解各種型別之間的比較。
不可比較的型別
在Go中,
切片
,
map
,和
func
是不可比較的,他們僅可以和預宣告表示符
nil
進行比較。能和nil進行比較的還有
指標
,
管道
和
interface{}
。
複數之間的比較
複數可比較但不可排序,實部和虛部均相等兩個複數才相等
。複數僅適用
==
和
!=
這兩個比較運算子:
上述輸出結果為
false
,證明覆數之間可比較。
此時程式無法執行,在vscode中的錯誤提醒為
cannot compare c1 >= c2 (operator >= not defined for complex128)compiler
。由此確認複數不可排序。
結構體之間的比較
如果結構體的所有欄位都是可比較的,則他們所有非匿名欄位的值相等,結構體的值才相等
。驗證如下:
上述輸出分別為
true
和
false
。由此驗證非匿名欄位的值相等,結構體的值才相等。
fmt。Println(st1 <= st2)
此行程式碼在vscode中的錯誤提醒為
cannot compare st1 <= st2 (operator <= not defined for canC)compiler
。由此可知,即使結構體滿足比較條件也無法適用於
<
,
<=
,
>
和
>=
運算子。
注
:後文中提到不可排序均代表著無法適用於
<
,
<=
,
>
和
>=
運算子,在後文中不再對不可排序給出例子。
下面看看包含匿名欄位的結構體比較時有什麼不同:
上述輸出為
true
,符合非匿名欄位的值相等時結構體的值相等這一原則。注意,
如果匿名欄位是不可比較的型別時,上述程式碼會編譯報錯
。
最後我們看看包含不可比較型別的結構體:
上述程式碼在vscode中的錯誤提醒為
cannot compare (canNotC literal) == (canNotC literal) (operator == not defined for canNotC)compiler
,由此可知,結構體如果要可比較,則其內部的所有欄位必須全為可比較型別。
指標之間的比較
指標是可比較的,但不可排序
。如果兩個指標指向同一個變數,或者兩個指標值均為nil,則這兩個指標相等。相信讀者對於這一點應該是沒有異議的,但是有一個情況卻是十分需要注意的。
zero-size variables
:如果結構體沒有任何欄位或者陣列沒有任何元素,則其大小為0,即
unsafe.Sizeof
的計算結果為0。兩個不同的
zero-size variables
在記憶體中可能具有相同的地址。
指向不同zero-size variables的兩個指標可能相等也可能不相等
。
筆者多次執行,
parr1 == parr2
始終輸出為
false
,目前尚未發現輸出為
true
的情況,在https://github。com/golang/go/issues/23440也有人遇到同筆者相同的情況,所以筆者就不再對此問題做更近一步的分析。
Channel之間的比較
在寫這篇文章前,筆者從來都沒有想過Channel之間是可以比較的。事實上,管道是可比較型別,golang原文如下:
Channel values are comparable。 Two channel values are equal if they were created by the same callto make orifboth have value nil
這裡需要注意的是,只有相同呼叫的管道才是相等的:
上述中,
cint1
和
cint2
初始值均為nil,所以輸出
true
。雙向通道
cint4
賦值給單向通道
cint1
時,滿足相同的
make
呼叫這一條件,所以輸出也為
true
。
Interface{}之間比較
Interface{}是可比較的,但是不可排序。兩個Interface{}變數的動態型別和動態value均一致它們才相等,兩個變數均為nil也是相等的
。針對這一原則筆者對其分以下幾種情況討論。
一、interface{}不為nil,且動態型別均為可比較型別時:
上述輸出結果為
true false false
,這符合
動態型別和動態value均一致時才相等
的原則。
二、
如果比較雙方動態型別一致且為不可比較型別時會panic
:
這種情況可正常編譯,但是會造成執行時崩潰,所以一定要注意!!!
fmt。Println(i5 == i6)
fmt。Println(i7 == i6)
上述比較
i5
和
i6
時能夠正常輸出,但是
i6
和
i7
比較時出現如下錯誤:
所以,筆者在這裡再次強調,如果專案中有不小心直接使用了
interface{}
進行比較的,請一定要注意。
三、動態value為nil的interface{}不一定等於nil:
由上述程式碼知,如果不是直接返回
nil
的
interface{}
和
nil
進行比較時是不相等的。相信很多人在平時的開發中都有可能會忽略這個問題。下面我們對它為什麼不相等進行簡單的分析。
在Go中,
interface{}
的實現為兩個元素,型別
t
和值
v
。v是一個具體的值,如int、struct、或指標等。
如果,我們在介面中儲存int值3,則介面中的值為(t=int,v=3)。
值v也稱為介面的動態值,因為在程式執行期間,給定的介面變數可能包含不同的值v(以及相應的型別t)。
只有當v和t都未設定時,介面值才是nil(t=nil,未設定v)。
如果,我們在介面中儲存一個型別為
int的nil指標, 那麼不管指標的值是什麼,內部型別都會是
int:(t=*int,v=nil)。因此,即使內部的指標v為nil,這樣的介面值也是非nil的。
本部分內容翻譯整理自https://golang。org/doc/faq#nil_error
非介面型別X實現了介面T,則X的變數x能和T的變數t進行比較
原則:
非介面型別X實現了介面T,則X的變數x能和T的變數t進行比較。只有當t的動態變數型別為X且t的動態value和x相等時,t才等於x
。
推論:又因為go中任意型別都預設實現了
interface{}
,則意味著
interface{}
變數能和任意的非
interface{}
型別的可比較型別進行比較。
驗證原則:
上面的輸出分別為
false
和
true
,符合原則。
驗證推論:
var it1 interface{} = “111”
fmt。Println(it1 == 1)
上面能夠正常比較,說明推論正確,且輸出為
false
,符合原則。
注意
:下面情況會panic
上述程式碼發生panic,符和
Interface{}
之間比較的原則。
陣列之間的比較
兩個陣列的元素型別相同且是可比較型別,並且陣列的長度相同,則這兩個陣列可比較。當兩個可比較的陣列對應元素均相等時,則這兩個陣列相等。即使兩個陣列可比較,但依舊不可排序
。
型別相同但元素不可比較時:
上述程式碼在vscode中的錯誤為
cannot compare array1 == array2 (operator == not defined for [3][]int)compiler
,所以如果陣列元素為不可比較型別,則陣列也不可比較。
陣列元素可比較但陣列長度不一致時:
上述程式碼在vscode中的錯誤為
cannot compare array3 == array4 (mismatched types [3]int and [2]int)compiler
,所以如果陣列長度不一致時,則兩個陣列不可比較。
滿足陣列長度相等且元素型別可比較時:
上述輸出分別為
true
和
false
,符合可比較陣列一一判斷對應元素是否相等這一原則。所以,我們平時在開發中可以利用該原則快速比較陣列是否相等。
最後,衷心希望本文能夠對各位讀者有一定的幫助。
注
:
寫本文時, 筆者所用go版本為: go1。14。2
文章中所用完整例子:https://github。com/Isites/go-coder/blob/master/comparison-operators/main。go
參考:
https://golang。org/ref/spec#Comparison_operators
推薦文章
- 國產退役大軍艦迎江而上,引發全民圍觀,未來還有更大驚喜!
由於目前中國海軍的新艦建造服役速度要遠遠快於老艦的退役速度,因此,未來還有更大驚喜,中國海軍現役導彈驅逐艦的數量在未來10年內追平美國海軍也並不是完全不可能的事情...
- 一張嘴就有一股臭味,怎麼刷牙都沒用?1分鐘瞭解口臭“根源”
要保持口氣清新,很多人會第一時間想到刷牙,這固然是最直接最根本的處理辦法,但出門在外,不可能時刻準備牙膏、牙刷、漱口水這類口腔清潔用品,無奈火鍋、烤肉太過吸引,還有很多人無大蒜、洋蔥、辣椒、榴蓮不歡,如果有一款能隨身攜帶口氣清新產品就太好了...
- 簡單易學的印尼醬油膏炒麵,GET 新技能!
用料乾麵條(泡麵餅更好)1人份胡蘿蔔1根捲心菜1/4顆洋蔥酥(熱狗裡用的就ok)3大勺印尼甜醬油膏KetjapManis2大勺糖、鹽各半小勺白胡椒1/4小勺雞蛋製作煎蛋,1個或者不新增做法1準備好喜愛的蔬菜,甜椒絲,土豆絲,洋蔥絲,白蘿蔔...