Go 會(huì)接替 Java,成為下一個(gè)企業(yè)級編程語言嗎?

2021-02-17    分類: 網(wǎng)站建設(shè)

基于現(xiàn)實(shí)經(jīng)驗(yàn)

Go 是由經(jīng)驗(yàn)豐富的軟件行業(yè)老手一手創(chuàng)建的,長期以來,他們對現(xiàn)有語言的各種缺點(diǎn)有過切身體會(huì)的痛苦經(jīng)歷。幾十年前,Rob Pike 和 Ken Thompson 在 Unix、C 和 Unicode 的發(fā)明中起到了重要作用。Robert Griensemer 在為 JavaScript 和 Java 開發(fā) V8 和 HotSpot 虛擬機(jī)之后,在編譯器和垃圾收集方面擁有數(shù)十年的經(jīng)驗(yàn)。有太多次,他們不得不等待 Google 規(guī)模的 C++/Java 代碼庫進(jìn)行編譯。于是,他們開始著手創(chuàng)建新的編程語言,將他們半個(gè)世紀(jì)以來的編寫代碼所學(xué)到的一切經(jīng)驗(yàn)包含進(jìn)去。

專注于大型工程

小型工程項(xiàng)目幾乎可以用任何編程語言來成功構(gòu)建。當(dāng)成千上萬的開發(fā)人員在數(shù)十年的持續(xù)時(shí)間壓力下,在包含數(shù)千萬行代碼的大型代碼庫上進(jìn)行協(xié)作時(shí),就會(huì)發(fā)生真正令人痛苦的問題。這樣會(huì)導(dǎo)致一些問題,如下:

  • 較長的編譯時(shí)間導(dǎo)致中斷開發(fā)。
  • 代碼庫由幾個(gè)人 / 團(tuán)隊(duì) / 部門 / 公司所擁有,混合了不同的編程風(fēng)格。
  • 公司雇傭了數(shù)千名工程師、架構(gòu)師、測試人員、運(yùn)營專家、審計(jì)員、實(shí)習(xí)生等,他們需要了解代碼庫,但也具備廣泛的編碼經(jīng)驗(yàn)。
  • 依賴于許多外部庫或運(yùn)行時(shí),其中一些不再以原始形式存在。
  • 在代碼庫的生命周期中,每行代碼平均被重寫 10 次,被弄得千瘡百痍,而且還會(huì)發(fā)生技術(shù)偏差。
  • 文檔不完整。

Go 注重減輕這些大型工程的難題,有時(shí)會(huì)以使小型工程變得更麻煩為代價(jià),例如,代碼中到處都需要幾行額外的代碼行。

注重可維護(hù)性

Go 強(qiáng)調(diào)盡可能多地將工作轉(zhuǎn)給自動(dòng)化的代碼維護(hù)工具中。Go 工具鏈提供了最常用的功能,如格式化代碼和導(dǎo)入、查找符號的定義和用法、簡單的重構(gòu)以及代碼異味的識(shí)別。由于標(biāo)準(zhǔn)化的代碼格式和單一的慣用方式,機(jī)器生成的代碼更改看起來非常接近 Go 中人為生成的更改并使用類似的模式,從而允許人機(jī)之間更加無縫地協(xié)作。

保持簡單明了

初級程序員為簡單的問題創(chuàng)建簡單的解決方案。高級程序員為復(fù)雜的問題創(chuàng)建復(fù)雜的解決方案。偉大的程序員找到復(fù)雜問題的簡單解決方案?!狢harles Connell

讓很多人驚訝的一點(diǎn)是,Go 居然不包含他們喜歡的其他語言的概念。Go 確實(shí)是一種非常小巧而簡單的語言,只包含正交和經(jīng)過驗(yàn)證的概念的最小選擇。這鼓勵(lì)開發(fā)人員用最少的認(rèn)知開銷來編寫盡可能簡單的代碼,以便許多其他人可以理解并使用它。

使事情清晰明了

良好的代碼總是顯而易見的,避免了那些小聰明、難以理解的語言特性、詭異的控制流和兜圈子。

許多語言都致力提高編寫代碼的效率。然而,在其生命周期中,人們閱讀代碼的時(shí)間卻遠(yuǎn)遠(yuǎn)超過最初編寫代碼所需的時(shí)間(100 倍)。例如,審查、理解、調(diào)試、更改、重構(gòu)或重用代碼。在查看代碼時(shí),往往只能看到并理解其中的一小部分,通常不會(huì)有完整的代碼庫概述。為了解釋這一點(diǎn),Go 將所有內(nèi)容都明確出來。

錯(cuò)誤處理就是一個(gè)例子。讓異常在各個(gè)點(diǎn)中斷代碼并在調(diào)用鏈上冒泡會(huì)更容易。Go 需要手動(dòng)處理和返回每個(gè)錯(cuò)誤。這使得它可以準(zhǔn)確地顯示代碼可以被中斷的位置以及如何處理或包裝錯(cuò)誤??偟膩碚f,這使得錯(cuò)誤處理編寫起來更加繁瑣,但是也更容易理解。

簡單易學(xué)

Go 是如此的小巧而簡單,以至于人們可以在短短幾天內(nèi)就能研究通整個(gè)語言及其基本概念。根據(jù)我們的經(jīng)驗(yàn),培訓(xùn)用不了一個(gè)星期(相比于掌握其他語言需要幾個(gè)月),初學(xué)者就能夠理解 Go 專家編寫的代碼,并為之做出貢獻(xiàn)。為了方便吸引更多的用戶,Go 網(wǎng)站提供了所有必要的教程和深入研究的文章。這些教程在瀏覽器中運(yùn)行,允許人們在將 Go 安裝到本地計(jì)算機(jī)上之前就能夠?qū)W習(xí)和使用 Go。

解決之道

Go 強(qiáng)調(diào)的是團(tuán)隊(duì)之間的合作,而不是個(gè)人的自我表達(dá)。

在 Go(和 Python)中,所有的語言特性都是相互正交和互補(bǔ)的,通常有一種方法可以做一些事情。如果你想讓 10 個(gè) Python 或 Go 程序員來解決同一個(gè)問題,你將會(huì)得到 10 個(gè)相對類似的解決方案。不同的程序員在彼此的代碼庫中感覺更自在。在查看其他人的代碼時(shí),國罵會(huì)更少,而且人們的工作可以更好地融合在一起,從而形成了一致的整體,人人都為之感到自豪,并樂于工作。這還避免了大型工程的問題,如:

  • 開發(fā)人員認(rèn)為良好的工作代碼很“混亂”,并要求在開始工作之前進(jìn)行重寫,因?yàn)樗麄兊乃季S方式與原作者不同。
  • 不同的團(tuán)隊(duì)成員使用不同的語言子集來編寫相同代碼庫的部分內(nèi)容。


簡單、內(nèi)置的并發(fā)性

Go 專為現(xiàn)代多核硬件設(shè)計(jì)。

目前使用的大多數(shù)編程語言(Java、JavaScript、Python、Ruby、C、C++)都是 20 世紀(jì) 80 年代到 21 世紀(jì)初設(shè)計(jì)的,當(dāng)時(shí)大多數(shù) CPU 只有一個(gè)計(jì)算內(nèi)核。這就是為什么它們本質(zhì)上是單線程的,并將并行化視為邊緣情況的馬后炮。通過現(xiàn)成和同步點(diǎn)之類的附加組件來實(shí)現(xiàn),而這些附加組件既麻煩又難以正確使用。第三方庫雖然提供了更簡單的并發(fā)形式,如 Actor 模型,但是總有多個(gè)可用選項(xiàng),結(jié)果導(dǎo)致了語言生態(tài)系統(tǒng)的碎片化。今天的硬件擁有越來越多的計(jì)算內(nèi)核,軟件必須并行化才能高效運(yùn)行。Go 是在多核處理器時(shí)代編寫的,并且在語言中內(nèi)置了簡單、高級的 CSP 風(fēng)格并發(fā)性。

面向計(jì)算的語言原語

就深層而言,計(jì)算機(jī)系統(tǒng)接收數(shù)據(jù),對其進(jìn)行處理(通常要經(jīng)過幾個(gè)步驟),然后輸出結(jié)果數(shù)據(jù)。例如,Web 服務(wù)器從客戶端接收 HTTP 請求,并將其轉(zhuǎn)換為一系列數(shù)據(jù)庫或后端調(diào)用。一旦這些調(diào)用返回,它就將接收到的數(shù)據(jù)轉(zhuǎn)換成 HTML 或 JSON 并將其輸出給調(diào)用者。Go 的內(nèi)置語言原語直接支持這種范例:

  • 結(jié)構(gòu)表示數(shù)據(jù)
  • 讀和寫代表流式 IO
  • 函數(shù)過程數(shù)據(jù)
  • goroutines 提供(幾乎無限的)并發(fā)性
  • 在并行處理步驟之間傳輸管道數(shù)據(jù)

因?yàn)樗械挠?jì)算原語都是由語言以直接形式提供的,因此 Go 源代碼更直接地表達(dá)了服務(wù)器執(zhí)行的操作。

OO?—?好的部分


更改基類中的某些內(nèi)容的副作用

面向?qū)ο蠓浅S杏谩_^去幾十年來,面向?qū)ο蟮氖褂酶挥谐尚В⒆屛覀兞私饬怂哪男┎糠直绕渌糠帜軌蚋玫財(cái)U(kuò)展。Go 在面向?qū)ο蠓矫娌捎昧艘环N全新的方法,并記住了這些知識(shí)。它保留了好的部分,如封裝、消息傳遞等。Go 還避免了繼承,因?yàn)樗F(xiàn)在被認(rèn)為是有害的,并為組合提供了的支持。

現(xiàn)代標(biāo)準(zhǔn)庫

目前使用的許多編程語言(Java、JavaScript、Python、Ruby)都是在互聯(lián)網(wǎng)成為當(dāng)今無處不在的計(jì)算平臺(tái)之前設(shè)計(jì)的。因此,這些語言的標(biāo)準(zhǔn)庫只提供了相對通用的網(wǎng)絡(luò)支持,而這些網(wǎng)絡(luò)并沒有針對現(xiàn)代互聯(lián)網(wǎng)進(jìn)行優(yōu)化。Go 是十年前創(chuàng)建的,當(dāng)時(shí)互聯(lián)網(wǎng)已全面發(fā)展。Go 的標(biāo)準(zhǔn)庫允許在沒有第三方庫的情況下創(chuàng)建更復(fù)雜的網(wǎng)絡(luò)服務(wù)。這就避免了第三方庫的常見問題:

  • 碎片化:總是有多個(gè)選項(xiàng)實(shí)現(xiàn)相同的功能。
  • 膨脹:庫常常實(shí)現(xiàn)的不僅僅是它們的用途。
  • 依賴地獄:庫通常依賴于特定版本的其他庫。
  • 未知質(zhì)量:第三方代碼的質(zhì)量和安全性可能存在問題。
  • 未知支持:第三方庫的開發(fā)可能隨時(shí)停止支持。
  • 意外更改:第三方庫通常不像標(biāo)準(zhǔn)庫那樣嚴(yán)格地進(jìn)行版本控制。

關(guān)于這方面更多的信息請參考 Russ Cox 提供的資料:https://research.swtch.com/deps

標(biāo)準(zhǔn)化格式

Gofmt 的風(fēng)格沒有人會(huì)去喜歡,但人人都會(huì)喜歡 gofmt?!猂ob Pike

Gofmt 是一種以標(biāo)準(zhǔn)化方式來格式化 Go 代碼的程序。它不是最漂亮的格式化方式,但卻是最簡單、最不令人生厭的格式化方式。標(biāo)準(zhǔn)化的源代碼格式具有驚人的積極影響:

  1. 集中討論重要主題:?它消除了圍繞制表符和空格、縮進(jìn)深度、行長、空行、花括號的位置等一系列爭論。
  2. 開發(fā)人員在彼此的代碼庫中感覺很自在,?因?yàn)槠渌a看起來很像他們編寫的代碼。每個(gè)人都喜歡自由地按照自己喜歡的方式進(jìn)行格式化代碼,但如果其他人按照自己喜歡的方式格式化了代碼,這么做很招人煩。
  3. 自動(dòng)代碼更改并不會(huì)打亂手寫代碼的格式,例如引入了意外的空白更改。

許多其他語言社區(qū)現(xiàn)在正在開發(fā)類似 gofmt 的東西。當(dāng)作為第三方解決方案構(gòu)建時(shí),通常會(huì)有幾個(gè)相互競爭的格式標(biāo)準(zhǔn)。例如,JavaScript 提供了 Prettier 和 StandardJS。這兩者都可以用,也可以只使用其中的一個(gè)。但許多 JS 項(xiàng)目并沒有采用它們,因?yàn)檫@是一個(gè)額外的決策。Go 的格式化程序內(nèi)置于該語言的標(biāo)準(zhǔn)工具鏈中,因此只有一個(gè)標(biāo)準(zhǔn),每個(gè)人都在使用它。

快速編譯


對于大型代碼庫來說,它們長時(shí)間的編譯是促使 Go 誕生的原因。Google 主要使用的是 C++ 和 Java,與 Haskell、Scala 或 Rust 等更復(fù)雜的語言相比,它們的編譯速度相對較快。盡管如此,當(dāng)編譯大型代碼庫時(shí),即使是少量的緩慢也會(huì)加劇編譯的延遲,從而激怒開發(fā)人員,并干擾流程。Go 的設(shè)計(jì)初衷是為了提高編譯效率,因此它的編譯器速度非???,幾乎沒有編譯延遲的現(xiàn)象。這給 Go 開發(fā)人員提供了與腳本類語言類似的即時(shí)反饋,還有靜態(tài)類型檢查的額外好處。

交叉編譯

由于語言運(yùn)行時(shí)非常簡單,因此它被移植到許多平臺(tái),如 macOS、Linux、Windows、BSD、ARM 等。Go 可以開箱即用地為所有這些平臺(tái)編譯二進(jìn)制文件。這使得從一臺(tái)機(jī)器進(jìn)行部署變得很容易。

快速執(zhí)行

Go 的運(yùn)行速度接近于 C。與 JITed 語言(Java、JavaScript、Python 等)不同,Go 二進(jìn)制文件不需要啟動(dòng)或預(yù)熱的時(shí)間,因?yàn)樗鼈兪亲鳛榫幾g和完全優(yōu)化的本地代碼的形式發(fā)布的。Go 的垃圾收集器僅引入微秒量級的可忽略的停頓。除了快速的單核性能外,Go 還可以輕松利用所有的 CPU 內(nèi)核。

內(nèi)存占用小

像 JVM、Python 或 Node 這樣的運(yùn)行時(shí)不僅僅在運(yùn)行時(shí)加載程序代碼,每次運(yùn)行程序時(shí),它們還會(huì)加載大型且高度復(fù)雜的基礎(chǔ)架構(gòu),以進(jìn)行編譯和優(yōu)化程序。如此一來,它們的啟動(dòng)時(shí)間就變慢了,并且還占用了大量內(nèi)存(數(shù)百兆字節(jié))。而 Go 進(jìn)程的開銷更小,因?yàn)樗鼈円呀?jīng)完全編譯和優(yōu)化,只需運(yùn)行即可。Go 還以非常節(jié)省內(nèi)存的方式來存儲(chǔ)數(shù)據(jù)。在內(nèi)存有限且昂貴的云環(huán)境中,以及在開發(fā)過程中,這一點(diǎn)非常重要。我們希望在一臺(tái)機(jī)器上能夠快速啟動(dòng)整個(gè)堆棧,同時(shí)將內(nèi)存留給其他軟件。

部署規(guī)模小

Go 的二進(jìn)制文件大小非常簡潔。Go 應(yīng)用程序的 Docker 鏡像通常比用 Java 或 Node 編寫的等效鏡像要小 10 倍,這是因?yàn)樗鼰o需包含編譯器、JIT,以及更少的運(yùn)行時(shí)基礎(chǔ)架構(gòu)的原因。這些特點(diǎn),在部署大型應(yīng)用程序時(shí)很重要。想象一下,如果要將一個(gè)簡單的應(yīng)用程序部署到 100 個(gè)生產(chǎn)服務(wù)器上會(huì)怎么樣?如果使用 Node/JVM 時(shí),我們的 Docker 注冊表就必須提供 100 個(gè) docker 鏡像,每個(gè)鏡像 200MB,那么一共就需要 20GB。要完成這些部署就需要一些時(shí)間。想象一下,如果我們想每天部署 100 次的話,如果使用 Go 服務(wù),那么 Docker 注冊表只需提供 10 個(gè) docker 鏡像,每個(gè)鏡像只有 20MB,共只需 2GB 即可。大型 Go 應(yīng)用程序可以更快、更頻繁地部署,從而使得重要更新能夠更快地部署到生產(chǎn)環(huán)境中。

獨(dú)立部署

Go 應(yīng)用程序部署為一個(gè)包含所有依賴項(xiàng)的單個(gè)可執(zhí)行文件,并無需安裝特定版本的 JVM、Node 或 Python 運(yùn)行時(shí);也不必將庫下載到生產(chǎn)服務(wù)器上,更無須對運(yùn)行 Go 二進(jìn)制文件的機(jī)器進(jìn)行任何更改。甚至也不需要講 Go 二進(jìn)制文件包裝到 Docker 來共享他們。你需要做的是,只是將 Go 二進(jìn)制文件放到服務(wù)器上,它就會(huì)在那里運(yùn)行,而不用關(guān)心服務(wù)器運(yùn)行的是什么。前面所提到的那些,唯一的例外是使用net和os/user包時(shí)針對對glibc的動(dòng)態(tài)鏈接。

供應(yīng)依賴關(guān)系

Go 有意識(shí)避免使用第三方庫的中央存儲(chǔ)庫。Go 應(yīng)用程序直接鏈接到相應(yīng)的 Git 存儲(chǔ)庫,并將所有相關(guān)代碼下載(供應(yīng))到自己的代碼庫中。這樣做有很多好處:

  • 在使用第三方代碼之前,我們可以對其進(jìn)行審查、分析和測試。該代碼就和我們自己的代碼一樣,是我們應(yīng)用程序的一部分,應(yīng)該遵循相同的質(zhì)量、安全性和可靠性標(biāo)準(zhǔn)。
  • 無需永久訪問存儲(chǔ)依賴項(xiàng)的各個(gè)位置。從任何地方(包括私有 Git repos)獲取第三方庫,你就能永久擁有它們。
  • 經(jīng)過驗(yàn)收后,編譯代碼庫無需進(jìn)一步下載依賴項(xiàng)。
  • 若互聯(lián)網(wǎng)某處的代碼存儲(chǔ)庫突然提供不同的代碼,這也并不足為奇。
  • 即使軟件包存儲(chǔ)庫速度變慢,或托管包不復(fù)存在,部署也不會(huì)因此中斷。

兼容性保證

Go 團(tuán)隊(duì)承諾現(xiàn)有的程序?qū)?huì)繼續(xù)適用于新一代語言。這使得將大型項(xiàng)目升級到最新版本的編譯器會(huì)非常容易,并且可從它們帶來的許多性能和安全性改進(jìn)中獲益。同時(shí),由于 Go 二進(jìn)制文件包含了它們需要的所有依賴項(xiàng),因此可以在同一服務(wù)器上并行運(yùn)行使用不同版本的 Go 編譯器編譯的二進(jìn)制文件,而無需進(jìn)行復(fù)雜的多個(gè)版本的運(yùn)行時(shí)設(shè)置或虛擬化。

文檔

在大型工程中,文檔對于使軟件可訪問性和可維護(hù)性非常重要。與其他特性類似,Go 中的文檔簡單實(shí)用:

  • 由于它是嵌入到源代碼中的,因此兩者可以同時(shí)維護(hù)。
  • 它不需要特殊的語法,文檔只是普通的源代碼注釋。
  • 可運(yùn)行單元測試通常是最好的文檔形式。因此 Go 要求將它們嵌入到文檔中。
  • 所有的文檔實(shí)用程序都內(nèi)置在工具鏈中,因此每個(gè)人都使用它們。
  • Go linter 需要導(dǎo)出元素的文檔,以防止“文檔債務(wù)”的積累。

商業(yè)支持的開源

當(dāng)商業(yè)實(shí)體在開放式環(huán)境下開發(fā)時(shí),那么一些最流行的、經(jīng)過徹底設(shè)計(jì)的軟件就會(huì)出現(xiàn)。這種設(shè)置結(jié)合了商業(yè)軟件開發(fā)的優(yōu)勢——一致性和精細(xì)化,使系統(tǒng)更為健壯、可靠、高效,并具有開放式開發(fā)的優(yōu)勢,如來自許多行業(yè)的廣泛支持,多個(gè)大型實(shí)體和許多用戶的支持,以及即使商業(yè)支持停止的長期支持。Go 就是這樣發(fā)展起來的。

缺點(diǎn)

當(dāng)然,Go 也并非好無缺,每種技術(shù)選擇都是有利有弊。在決定選擇 Go 之前,有幾個(gè)方面需要進(jìn)行考慮考慮。

未成熟

雖然 Go 的標(biāo)準(zhǔn)庫在支持許多新概念(如 HTTP 2 Server push 等)方面處于行業(yè)地位,但與 JVM 生態(tài)系統(tǒng)中的第三方庫相比,用于外部 API 的第三方 Go 庫可能不那么成熟。

即將到來的改進(jìn)

由于清楚幾乎不可能改變現(xiàn)有的語言元素,Go 團(tuán)隊(duì)非常謹(jǐn)慎,只在新特性完全開發(fā)出來后才添加新特性。在經(jīng)歷了 10 年的有意穩(wěn)定階段之后,Go 團(tuán)隊(duì)正在謀劃對語言進(jìn)行一系列更大的改進(jìn),作為 Go 2.0 之旅的一部分。

無硬實(shí)時(shí)

雖然 Go 的垃圾收集器只引入了非常短暫的停頓,但支持硬實(shí)時(shí)需要沒有垃圾收集的技術(shù),例如 Rust。

結(jié)語

本文詳細(xì)介紹了 Go 語言的一些優(yōu)秀的設(shè)計(jì)準(zhǔn)則,雖然有的準(zhǔn)則的好處平常看起來沒有那么明顯。但當(dāng)代碼庫和團(tuán)隊(duì)規(guī)模增長幾個(gè)數(shù)量級時(shí),這些準(zhǔn)則可能會(huì)使大型工程項(xiàng)目免于許多痛苦。總的來說,正是這些設(shè)計(jì)準(zhǔn)則讓 Go 語言成為了除 Java 之外的編程語言里,用于大型軟件開發(fā)項(xiàng)目的好選擇。

網(wǎng)站名稱:Go 會(huì)接替 Java,成為下一個(gè)企業(yè)級編程語言嗎?
文章位置:http://www.bm7419.com/news39/101539.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、定制網(wǎng)站、企業(yè)建站移動(dòng)網(wǎng)站建設(shè)、云服務(wù)器、標(biāo)簽優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營