PHP vs Go,為什么 Go 不支持命名參數(shù)調(diào)用函數(shù)?
大家好,我是煎魚。
之前在《Go 語(yǔ)言設(shè)計(jì)哲學(xué)[1]》電子書中分享了《??為什么 Go 不支持函數(shù)重載和缺省參數(shù)???》的思考和原因。最近有一位從其他編程語(yǔ)言轉(zhuǎn)型 Go 的同學(xué)提出了如下靈魂拷問。
“為什么 Go 不能像 PHP、Python 一樣,在調(diào)用函數(shù)時(shí),直接帶上參數(shù)名和值一起傳入。這樣就不用特意去看這個(gè)函數(shù)的形參的命名、類型等。明明 PHP8 都支持了?”
今天針對(duì)命名參數(shù)這個(gè)特性展開思考,看看 Go 怎么回事。
命名參數(shù)
如果有了命名參數(shù)這個(gè)功能特性,在我們調(diào)用函數(shù)/方法時(shí),傳入函數(shù)的參數(shù)不需要固定位置,位置可以隨意調(diào)整,名字對(duì)就行。甚至有的工具會(huì)基于此,做自動(dòng)化的文檔等自描述的場(chǎng)景。
PHP8 的例子:
理想中 Go 的例子:
由于不支持,運(yùn)行編譯就會(huì)報(bào)錯(cuò):
Go 必須是如下代碼:
也就是按函數(shù)所聲明的參數(shù)位置傳入,才能運(yùn)行成功。
設(shè)計(jì)哲學(xué)
Go 語(yǔ)言在錯(cuò)誤處理、函數(shù)重載以及缺省參數(shù)等社區(qū)議題討論時(shí),總會(huì)祭出其的設(shè)計(jì)理念是:“顯式大于隱喻”,追求明確,顯式,要不就是 “l(fā)ess is more”。
每次看到只要不滿足這個(gè)理念的提案、討論,基本 Go 團(tuán)隊(duì)可以圍繞這個(gè)論據(jù)給出一堆理由后拒絕掉。
本文提到的帶命名參數(shù)傳入函數(shù),看起來非常顯式,很明確了。似乎很符合 Go 的設(shè)計(jì)哲學(xué)理念,感覺不應(yīng)該沒有才對(duì)?
社區(qū)思考
在 golang-nuts 郵件群組的多年討論中,涉及到以下幾類論據(jù)作為支撐:
- 這是一個(gè)語(yǔ)言設(shè)計(jì)和可讀性問題,“命名參數(shù)” 和 “缺省參數(shù)” 基本是成配套出現(xiàn)在語(yǔ)言設(shè)計(jì)中,需要一并考量合適與否。會(huì)出現(xiàn)一加就相當(dāng)于要引入許多新語(yǔ)法特性了,能玩出騷操作。
- 引入這類特性會(huì)給 Go 帶來新語(yǔ)法復(fù)雜度,如果函數(shù)參數(shù)名修改了,那是不是破壞兼容性?是不是調(diào)用方全都得改一遍?如果出現(xiàn)同名的參數(shù)名,誰(shuí)先誰(shuí)后?怎么覆蓋?過長(zhǎng)的話,函數(shù)調(diào)用會(huì)不會(huì)過于難接受?組合結(jié)構(gòu)體覆蓋方法時(shí),方法參數(shù)名需不需要保持一致?會(huì)產(chǎn)生一大堆新問題。
- 引入后會(huì)產(chǎn)生大量的函數(shù)可選參數(shù)(命名參數(shù)+缺省參數(shù)),原本只需要知道函數(shù)形參是什么,結(jié)果引入后需要查看名字、缺省值以及對(duì)應(yīng)的缺省邏輯等,會(huì)加大程序員心智負(fù)擔(dān)。
- 編譯器本身不需要關(guān)注這些信息,為這個(gè)特性加大編譯器的各項(xiàng)開銷是不必要的,沒有理由讓編譯器在編譯代碼中存儲(chǔ)函數(shù)的參數(shù)名稱(需要具體考究深意)。
我們?cè)谟懻撝幸灿刑岬剑@個(gè)特性可以借助 go:generate 的特性來實(shí)現(xiàn)類似的功能,有興趣的朋友可以看看 go-named-params[2] 這個(gè)開源庫(kù)。
顯然官方態(tài)度是,增加命名參數(shù)特性的弊大于利,貿(mào)然增加會(huì)影響到 Go 本身標(biāo)榜的優(yōu)勢(shì)(簡(jiǎn)潔)。認(rèn)為大可不必加,工具的問題需要讓工具自己解決。
總結(jié)
在這篇文章中,我們針對(duì)其他編程語(yǔ)言既有的 “命名參數(shù)” 特性進(jìn)行了分析和說明。顯然 Go 團(tuán)隊(duì)在討論中,認(rèn)為該項(xiàng)特性對(duì)于靜態(tài)語(yǔ)言,尤其對(duì)于 Go 團(tuán)隊(duì)來講,似乎好處太少,加了會(huì)影響自己的風(fēng)格(less is more),還可能會(huì)影響性能,真是大可不必。
各語(yǔ)言間的功能特性對(duì)比,是個(gè)老大難的問題。如果都一樣,那豈不是搞個(gè)大單體編程語(yǔ)言算了?這顯然是不現(xiàn)實(shí)的。
參考資料
[1]Go 語(yǔ)言設(shè)計(jì)哲學(xué): https://golang3.eddycjy.com/
[2]go-named-params: https://github.com/elliotchance/go-named-params