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

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

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

Golang為何舍棄三元運算符

馬哥Linux運維 ? 來源:cnblogs ? 2024-04-03 15:13 ? 次閱讀

三元運算符廣泛存在于其他語言中,比如:

python

val = trueValue if expr else falseValue

javascript:

const val = expr ? trueValue : falseValue

c、c++

const char *val = expr ? "trueValue" : "falseValue";

然而,被廣泛支持的三目運算符在golang中卻是不存在的!如果我們寫出類似下面的代碼:

val := expr ? "trueValue" : "falseValue"

那么編譯器就該抱怨了:invalid character U+003F '?'。意思是golang中不存在?這個運算符,編譯器不認識而且非字母數(shù)字下劃線也不能用做變量名,自然也就當作是非法字符了。

然而這是為什么呢,其實官方給出了解釋,這里簡單引用一下:

The reason ?: is absent from Go is that the language's designers had seen the operation used too often to create impenetrably complex expressions. The if-else form, although longer, is unquestionably clearer. A language needs only one conditional control flow construct.

golang中不存在?:運算符的原因是因為語言設(shè)計者已經(jīng)預見到三元運算符經(jīng)常被用來構(gòu)建一些極其復雜的表達式。雖然使用if進行替代會讓代碼顯得更長,但這毫無疑問可讀性更強。一個語言只需要有一種條件判斷結(jié)構(gòu)就足夠了。

毫無疑問,這是在golang“大道至簡”的指導思想下的產(chǎn)物。

這段話其實沒問題,因為某些三元運算符的使用場景確實會降低代碼的可讀性:

const status = (type===1?(agagin===1?'再售':'已售'):'未售')
const word = (res.distance === 0) ? 'a'
: (res.distance === 1 && res.difference > 3) ? 'b'
: (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) ? 'c'
: 'd';

乍一看確實很復雜,至少第二個表達式不花個20秒細看可能沒法理清控制流程(想象一下當縮進錯位或是完全沒有縮進的時候)。

如果把它們直接轉(zhuǎn)化成if語句是這樣的:

let status = ''
if (type === 1) {
if (again === 1) {
status = '再售'
} else {
status = '已售'
}
} else {
status = '未售'
}
let word = ''
if (res.distance === 0) {
word = 'a'
} else {
if (res.distance === 1 && res.difference > 3) {
word = 'b'
} else {
if (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) {
word = 'c'
} else {
word = 'd'
}
}
}

看起來并沒有多少的改善,特別是例2,三層嵌套,不管是誰review到這段代碼難免不會抱怨你幾句。

然而事實上這些代碼是可以簡化的,考慮到三元運算符總是會給變量一個值,因此最后的else其實可以看作是變量的默認值,于是代碼可以這么寫:

let status = '未售'
if (type === 1) {
if (again === 1) {
status = '再售'
} else {
status = '已售'
}
}
let word = 'd'
if (res.distance === 0) {
word = 'a'
} else {
if (res.distance === 1 && res.difference > 3) {
word = 'b'
} else {
if (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) {
word = 'c'
}
}
}

其次,對于例2,顯然可以使用else if來清除嵌套結(jié)構(gòu):

let word = 'd'
if (res.distance === 0) {
word = 'a'
} else if (res.distance === 1 && res.difference > 3) {
word = 'b'
} else if (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) {
word = 'c'
}

現(xiàn)在再來看,顯然使用if語句的版本的可讀性更高,邏輯也更清晰(通過去除嵌套)。

然而事實也不盡然。除了用三元運算符表達流程控制之外,事實上更常見更廣泛的一個應用是如下這樣的表達式:

const val = expr ? trueValue : falseValue
const func = (age) => age > 18 ? '成年人' : '未成年人'

類似上述通過一個簡短的條件表達式來確定變量的值,在開發(fā)中的出現(xiàn)頻率是相當高的。這時三元運算符的意圖更清晰,可讀性也較if語句更高,特別是配合匿名函數(shù)(lambda表達式)使用可以極大簡化我們的代碼。

對此python的解決之道是之支持上述的簡化版三元表達式,同時表達式不支持嵌套,達到了揚長避短的目的。不過代價是編譯器的相關(guān)實現(xiàn)會復雜化。

而對于golang來說一個簡單的能只通過單遍掃描即可完成ast構(gòu)建的編譯器是其保持急速的構(gòu)建速度的秘訣之一,為了這樣簡單的功能增加編譯器實現(xiàn)的復雜度是不可接受的。同時由于golang“大道至簡”的哲學,能用現(xiàn)有語法結(jié)構(gòu)解決的問題,自然不會再添加新的語法。

不過還是有辦法的,雖然不推薦

func If(cond bool, a, b interface{}) {
if cond {
return a
}
return b
}
age := 20
val := If(age > 18, "成年人", "未成年人").(string)

不推薦這么做是有幾個原因:

使用接口導致性能下降

需要強制的類型斷言

不管三元表達式還是if語句,對于不會到達的分支是不會計算的,也就是惰性計算;而給函數(shù)傳遞參數(shù)時每一個表達式都會被計算

最后總結(jié)一下:

三元運算符的優(yōu)點:

對于簡短的表達式使用三元運算符表意更清晰,特別是在習慣了線性閱讀三元運算符表達式之后

不需要中間狀態(tài)(例如第一個例子中的let變量可以替換為const,代碼更健壯),心智負擔更低

沒有中間狀態(tài)也就意味著更少或完全沒有副作用,代碼更易跟蹤和維護

但三元運算符也有明顯的缺點:

對于復雜邏輯代碼可讀性較差(例如第一個例子中的status,需要在trueValue的位置進行進一步的條件判斷時)

容易被濫用,很多人將其用于替代if語句或是簡化復雜的if嵌套,這會導致上一條中所描述的結(jié)果

條件分支只能為表達式,不支持多條語句

所以這是一個見仁見智的問題,總之只能入鄉(xiāng)隨俗了。

審核編輯:黃飛

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

    關(guān)注

    1

    文章

    1617

    瀏覽量

    49015
  • 運算符
    +關(guān)注

    關(guān)注

    0

    文章

    170

    瀏覽量

    11048

原文標題:為什么golang中不存在三元運算符

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

收藏 人收藏

    評論

    相關(guān)推薦

    C語言運算符的使用方法

    詳細介紹了C語言表達式、算術(shù)運算符、賦值運算符、關(guān)系運算符、條件結(jié)構(gòu)、邏輯運算符、位運算符的語法和使用方法,并討論了
    發(fā)表于 11-02 11:30 ?1415次閱讀
    C語言<b class='flag-5'>運算符</b>的使用方法

    如何去使用運算符?

    運算的定義是什么?運算符是由什么組成的?如何去使用運算符?
    發(fā)表于 07-15 13:13

    條件運算符是什么_條件運算符有哪些

    運算符優(yōu)先級高于賦值、逗號運算符,低于其他運算符。關(guān)系運算實際上是邏輯比較運算,它是邏輯運算
    發(fā)表于 11-16 16:02 ?1.1w次閱讀
    條件<b class='flag-5'>運算符</b>是什么_條件<b class='flag-5'>運算符</b>有哪些

    單目運算符是什么_單目運算符有哪些

    單目運算符是指運算所需變量為一個的運算符,又叫一運算符,其中有邏輯非運算符:!、按位取反
    的頭像 發(fā)表于 02-24 15:42 ?6w次閱讀
    單目<b class='flag-5'>運算符</b>是什么_單目<b class='flag-5'>運算符</b>有哪些

    C運算符的優(yōu)先級和結(jié)合性詳細解決

    運算符是一種告訴編譯器執(zhí)行特定的數(shù)學或邏輯操作的符號。 C語言內(nèi)置了豐富的運算符,大體可分為10類:算術(shù)運算符、關(guān)系運算符、邏輯運算符、位
    的頭像 發(fā)表于 02-22 17:27 ?3185次閱讀

    淺析MySQL中的各類運算符

    MySQL支持多種運算符,我們在寫SQL腳本時經(jīng)常會需要用到各種各樣的運算符,這些運算符可以用來連接表達式,進而從數(shù)據(jù)庫中查詢我們需要的結(jié)果集等。這些類型主要包括算術(shù)運算符、比較
    的頭像 發(fā)表于 05-03 17:41 ?2022次閱讀
    淺析MySQL中的各類<b class='flag-5'>運算符</b>

    干貨:大實例講解種C++運算符重載

    本章節(jié)主要講解是運算符重載。運算符重載是賦予運算符能操作自定義類型的功能。C++運算符重載主要分為以下類:
    的頭像 發(fā)表于 09-30 16:59 ?3404次閱讀
    干貨:<b class='flag-5'>三</b>大實例講解<b class='flag-5'>三</b>種C++<b class='flag-5'>運算符</b>重載

    python運算符是什么

    python運算符 0. 什么是運算符? 本章節(jié)主要說明Python的運算符。舉個簡單的例子 4 +5 = 9 。 例子中,4和5被稱為操作數(shù),“+”號為運算符。 Python語言支持
    的頭像 發(fā)表于 02-21 16:44 ?2341次閱讀

    SystemVerilog-運算符/表達式規(guī)則

    RTL建模中廣泛使用的運算符是條件運算符,也稱為三元運算符,該運算符用于在兩個表達式之間進行選擇——表5-2列出了用于表示條件
    的頭像 發(fā)表于 08-03 09:03 ?2999次閱讀

    如何靈活使用三元運算符

    給定四個無符號數(shù),請找出最小值。無符號數(shù)可以與標準比較運算符(a < b)進行比較。使用條件運算符描述一個兩路的最小值電路,然后組合它來創(chuàng)建一個4路最小電路??赡苄枰恍┚€向量作為中間結(jié)果。
    的頭像 發(fā)表于 09-28 17:07 ?1229次閱讀

    什么是運算符重載

    重載運算符是具有特殊名稱的函數(shù),是通過關(guān)鍵字** operator **后跟運算符的符號來定義的
    的頭像 發(fā)表于 01-20 15:30 ?2423次閱讀

    條件(三元運算符

    RTL建模中廣泛使用的運算符是條件運算符,也稱為三元運算符,該運算符用于在兩個表達式之間進行選擇——表5-2列出了用于表示條件
    的頭像 發(fā)表于 02-09 15:42 ?1297次閱讀
    條件(<b class='flag-5'>三元</b>)<b class='flag-5'>運算符</b>

    什么是移位運算符

    移位運算符將向量的位向右或向左移位指定的次數(shù)。SystemVerilog具有按位和算術(shù)移位運算符
    的頭像 發(fā)表于 02-09 15:49 ?1761次閱讀
    什么是移位<b class='flag-5'>運算符</b>

    Go語言運算符主要包括哪些呢?

    Go語言運算符主要包括:算數(shù)運算符、關(guān)系運算符、邏輯運算符、位運算符、賦值運算符和其他
    的頭像 發(fā)表于 05-26 15:54 ?822次閱讀
    Go語言<b class='flag-5'>運算符</b>主要包括哪些呢?

    c語言從右到左的運算符有哪些

    用在變量之后時,它們會先返回變量的原始值,然后再進行遞增或遞減。 三元條件運算符 ( ?: ):這個運算符的求值順序是從右到左。首先計算第個表達式,然后根據(jù)第一個表達式的結(jié)果選擇第二
    的頭像 發(fā)表于 08-20 11:39 ?602次閱讀