淺析Go常量為什么只支持基本數(shù)據(jù)類型
相信大家在接觸 Go 這門編程語(yǔ)言時(shí),就會(huì)學(xué)到常量這個(gè)知識(shí)點(diǎn)。
各大編程語(yǔ)言會(huì)教你,常量是不可變變量的一種類型。只要定義了常量,你就可以安心的用他。不用擔(dān)心值在哪里就被程序莫名奇妙的給改了。
常量的使用例子
如下例子:
const s string = "腦子進(jìn)煎魚了" func main() { fmt.Println(s) const n = 500000000 const d = 3e20 / n fmt.Println(d) fmt.Println(int64(d)) fmt.Println(math.Sin(n)) }
輸出結(jié)果:
腦子進(jìn)煎魚了
6e+11
600000000000
-0.28470407323754404
你可能會(huì)發(fā)現(xiàn)一個(gè)奇怪的點(diǎn)。那就是例子里都是基本的數(shù)據(jù)類型。那能不能用復(fù)雜點(diǎn)的數(shù)據(jù)類型呢,例如 Go 里比較經(jīng)典的切片。
如果是用 var 聲明:
var s = []string{"摸", "煎", "魚"} func main() { fmt.Println(s) }
正常輸出:[摸 煎 魚]
如果是用 const 聲明:
const s = []string{"摸", "煎", "魚"}
將會(huì)報(bào)錯(cuò):
./prog.go:7:11: []string{…} (value of type []string) is not constant
因?yàn)樵?Go 中,僅支持字符、字符串、布爾和數(shù)值類型的常量。這和其他編程語(yǔ)言間多多少少還是有點(diǎn)不一樣的。
為什么不支持更多類型
為什么在 Go 中常量只支持這幾種基礎(chǔ)類型,為什么沒(méi)法支持復(fù)雜類型,甚至是所有類型?
這是非常奇怪的。畢竟 PHP 都能支持:
class MyClass { const ABC = array('A', 'B', 'C'); const A = '1'; const B = '2'; const C = '3'; const NUMBERS = array( self::A, self::B, self::C, ); }
這又是出于什么緣由?
已有 10 年老提案
我認(rèn)真翻閱了 Go issues 等相關(guān)資料,終于發(fā)現(xiàn)竟然在 2013 年(10 年前),就已經(jīng)有人提出過(guò)這個(gè)提案:
提出者 @RickySeltzer,認(rèn)為:
var each1 = []byte{'e', 'a', 'c', 'h'}
可以正常運(yùn)行。
const each2 = []byte{'e', 'a', 'c', 'h'}
不行,直接報(bào)錯(cuò):prog.go:7: const initializer []byte literal is not a constant
。
他認(rèn)為這就是 Go 語(yǔ)言規(guī)范和設(shè)計(jì)上的缺陷,得改,得支持!
拒絕的論據(jù)是什么
對(duì)此也有各種爭(zhēng)論,老大哥 @Robert Griesemer,10 年前已
在為 Go 貢獻(xiàn),現(xiàn)在依然還在...他對(duì) Go 常量只支持基本類型這個(gè)設(shè)計(jì)給出了定論。
基于如下原因:
首先這不是語(yǔ)言的缺陷,也不是設(shè)計(jì)的缺陷。Go 語(yǔ)言的常量是故意設(shè)計(jì)成只支持基本類型。
基本類型到復(fù)雜類型的改變,這種變化的影響比我們看到的要深遠(yuǎn)得多。需要考慮很多問(wèn)題。
- 常量 channel、常量指針、常量 maps、常量 slice 都要支持嗎?
- 先支持常量 array 和 常量 struct?
- 要支持到什么程度,以什么來(lái)作為標(biāo)準(zhǔn)決定?
設(shè)計(jì)上,Go 團(tuán)隊(duì)期望類型系統(tǒng)(包括常量的含義)相對(duì)簡(jiǎn)單,以免在編譯時(shí)出現(xiàn)問(wèn)題。
- 常量更多類型的支持,會(huì)增加復(fù)雜性。不清楚這樣做的好處是否值得(ROI)。
- 常量是否可以尋址?const 數(shù)組的元素本身必須是 const 嗎?
匯總一下,潛臺(tái)詞就是:
- 設(shè)計(jì)如下:常量只支持基本類型,是 Go 設(shè)計(jì)上就是這么決定的。
- ROI 要衡量一下:沒(méi)有支持更多的復(fù)雜類型,是認(rèn)為好處不多。也沒(méi)有想清楚這塊的緣由。
- 少即是多:類型系統(tǒng)要保持少即是多(less is more)。
實(shí)戰(zhàn)中的騷操作
在相關(guān)提案的 issues 中看到歐神(@Changkun Ou)也參與了討論,他例舉了一個(gè)常量的經(jīng)典騷操作。
代碼如下:
- const ErrVerification = errors.New("crypto/rsa: verification error") + var ErrVerification = errors.New("crypto/rsa: verification error")
在對(duì)應(yīng)的 Go 工程中可能是這么使用:
import "cropto/rsa" func init() { rsa.ErrVerification = nil }
這個(gè)場(chǎng)景我還真見過(guò),一開始想定義 const,結(jié)果不支持。只能被迫 var。這不,就開天窗了。
總結(jié)
Go 核心團(tuán)隊(duì)在綜合衡量 ROI 后,認(rèn)為常量支持更多的類型在可預(yù)見的未來(lái)不會(huì)改變。因?yàn)閷⒊A康母拍顢U(kuò)展到基本類型之外將是一個(gè)重大變化,會(huì)產(chǎn)生各種影響。
在此刻(Go1)改變語(yǔ)言的門檻非常高,需要有明確的定義,要有完整的提案以及對(duì)成本和效益等的詳細(xì)分析。
如果出現(xiàn),只可能在未來(lái)的 Go2。但結(jié)合 rsc 最新的結(jié)論,沒(méi)有 Go2 的話,那如果未來(lái)真的做,那就是通過(guò) GODEBUG 和 go.mod 的 go 版本號(hào)來(lái)實(shí)現(xiàn)了。
常量更多類型的支持,雖然已經(jīng)提出了 10 年。但目前 Go 核心團(tuán)隊(duì)推進(jìn)乏力,想必,可能還要個(gè) 5 年吧。
以上就是淺析Go常量為什么只支持基本數(shù)據(jù)類型的詳細(xì)內(nèi)容,更多關(guān)于Go常量的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Go語(yǔ)言基礎(chǔ)語(yǔ)法和基本數(shù)據(jù)類型知識(shí)鞏固
- 夯實(shí)Golang基礎(chǔ)之?dāng)?shù)據(jù)類型梳理匯總
- Go語(yǔ)言數(shù)據(jù)類型簡(jiǎn)單介紹
- 深入了解Golang中的數(shù)據(jù)類型
- Golang數(shù)據(jù)類型比較詳解
- Go語(yǔ)言中的基礎(chǔ)數(shù)據(jù)類型使用實(shí)例
- 重學(xué)Go語(yǔ)言之基礎(chǔ)數(shù)據(jù)類型詳解
- 淺析Go語(yǔ)言的數(shù)據(jù)類型及數(shù)組
- Go語(yǔ)言中基本數(shù)據(jù)類型的相互轉(zhuǎn)換詳解
- Go基本數(shù)據(jù)類型的具體使用
相關(guān)文章
Go語(yǔ)言指針訪問(wèn)結(jié)構(gòu)體的方法
這篇文章主要介紹了Go語(yǔ)言指針訪問(wèn)結(jié)構(gòu)體的方法,涉及Go語(yǔ)言指針及結(jié)構(gòu)體的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02Golang編程并發(fā)工具庫(kù)MapReduce使用實(shí)踐
這篇文章主要為大家介紹了Golang并發(fā)工具庫(kù)MapReduce的使用實(shí)踐,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04如何在golang中使用shopspring/decimal來(lái)處理精度問(wèn)題
本文主要介紹了如何在golang中使用shopspring/decimal來(lái)處理精度問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04Go語(yǔ)言中的數(shù)據(jù)格式(json、xml?、msgpack、protobuf)使用總結(jié)
在分布式的系統(tǒng)中,因?yàn)樯婕暗綌?shù)據(jù)的傳輸,所以一定會(huì)進(jìn)行數(shù)據(jù)的交換,此時(shí)就要定義數(shù)據(jù)交換的格式,例如二進(jìn)制、Json、Xml等等。本文總結(jié)了Go語(yǔ)言中的數(shù)據(jù)格式,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07Go實(shí)現(xiàn)基于RSA加密算法的接口鑒權(quán)
這篇文章主要介紹了Go實(shí)現(xiàn)基于RSA加密算法的接口鑒權(quán),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06