做者介紹:Nick Cameron,PingCAP 研發工程師,Rust 語言核心成員。 程序員
感謝 Rust 語言中文社區夥伴們的翻譯和審校:編程
翻譯:尚卓燃
審校:吳聰、張漢東數組
過去幾周,我一直在用 Go 語言編寫程序。這是我首次在大型且重要的項目中使用 Go。在研究 Rust 的特性時,我也看了不少關於 Go 的內容,包括體驗示例和編寫玩具程序。但真正用它編程又是一種徹底不一樣的體驗。安全
我以爲把此次體驗寫下來應該會頗有趣。在這篇文章中,我會盡可能避免將 Go 與 Rust 進行過多的比較,不過,因爲我是從 Rust 轉向 Go,不免也會包含一些比較。應該事先聲明的是,我更偏袒 Rust ,但會盡力作到客觀。併發
用 Go 編程的感受很棒。庫程序裏有我想要的一切,整體實現較爲完善。學習體驗也十分順暢,不得不說,Go 是一種通過精心設計的實用性語言。舉個例子:一旦你知悉了 Go 的語法,就能將其餘語言中慣用法延續到 Go 中。只要你學會一些 Go,就能夠相對輕易地推測 Go 語言的其餘特性。憑藉一些來自其餘語言的知識,我可以閱讀並理解 Go 代碼,而不須要過多的搜索(Google)。app
與 C/C++、Java、Python 等相比,Go 並無那麼多痛點,並且更具生產力。然而,它仍是與這些語言處在同一個時代。儘管它從其餘語言身上吸收了一些教訓,甚至我我的認爲它多是那一代語言中最好的那個,但絕對還屬於那一代語言。這是一種漸進式的改進,而不是推陳出新(須要明確的是,這不是意味着對其價值的批判,從軟件工程的角度,漸進式改進一般會帶來好的影響)。一個很好的例證是 nil
:像 Rust 和 Swift 這樣的語言已經去除了 null
的概念,而且消除了相關的一整類錯誤。Go 下降了一部分風險:沒有空值(no null values),在 nil
和 0
之間進行區分。但其核心思想仍未改變,一樣還會出現解空指針引用這種常見的運行時錯誤。函數
Go 很是易學。我知道人們常常吹捧這一點,可是我真的爲本身生產力的飛速提升而感到震驚。多虧了 Go 語言以及它的文檔和工具,我僅僅花了兩天時間就能夠寫出「有價值」、能夠提交的代碼。工具
有助於易學性的幾個因素是:性能
Go 代碼很快就會變得很是重複。這是因爲它缺少宏或者泛型這種用於減小重複的機制(接口雖然有利於抽象,但在減小代碼重複方面做用沒有那麼大)。最終我會寫不少函數,而他們除了類型不一樣以外其餘甚至徹底同樣。學習
錯誤處理也會致使重複。許多函數中像 if err != nil { return err }
這樣的樣板式代碼甚至比那些真正有價值的代碼還要多。
使用泛型或宏來減小樣板式代碼有時會受到批評,理由是不該爲使代碼易於編寫而使其喪失可讀性。我發現 Go 偏偏提供了一個反例,複製和粘貼代碼每每既快速又簡單,閱讀代碼卻會使人灰心喪氣,由於你不得不忽略大量的無關代碼或者在大量的相同代碼中找到細微的不一樣。
if ...; ... { }
語法:能夠將變量的做用域限制在 if
語句真的很好。這與 Swift 及 Rust 中的 if let
起着類似的效果,但用途更爲普遍(Go 沒有像 Swift 和 Rust 那樣的模式匹配,因此它沒法使用 if let
)。如下內容沒有特定的順序。
nil
切片:要知道 nil
、nil
切片和空切片三者都不相同,我敢保證咱們只須要其中的兩個,而不須要第三個。switch
容許出現遺漏匹配的狀況。 for ... range
語句會返回一對「索引/值」。要想只獲取索引很容易(忽略值就好);但若要只獲取值,則須要顯式聲明。在我看來,這種作法更應該顛倒過來,由於在大多數狀況下,我更須要值而不是索引。語法:
return
語句中卻不須要。type
和 struct
)。還有我以前已經提過的,Go 缺乏泛型和宏。
做爲一名語言設計者和程序員,Go 最讓我驚訝的地方也許是它的內置功能和用戶可用功能之間頻頻出現不一致。許多語言的目標之一就是儘量消除編譯器魔法,讓用戶也能使用內置功能。運算符重載是一個簡單但有爭議的例子。但 Go 有不少魔法!你很容易就會遇到這樣的問題:沒法作那些內置功能能夠作的事情。
一些讓我印象深入的地方:
for ... range
語句對數組和切片進行迭代,但對其餘集合就無能爲力了,由於它缺少迭代器的概念。len
或者 append
這樣的函數是全局函數,但你本身的函數卻沒法轉變成全局函數。這些全局函數只能使用內置類型。即使 Go「沒有泛型」,它們也能夠變得通用。==
就會令人感到惱火。由於這意味着你不能在詞典中使用自定義類型做爲鍵,除非它們是可比較的。這一屬性派生自類型結構,程序員沒法重寫該屬性。Go 是一種簡單、小巧、使人愉悅的語言。它也有一些犄角旮旯,但絕大部分是通過精心設計的。它的學習速度使人難以置信,而且規避了其餘語言中一些不那麼廣爲人知的特性。
Go 也是一種與 Rust 大相徑庭的語言。雖然二者均可以籠統地描述爲「系統語言」或「C 語言的替代品」,但它們的設計目標、應用領域、語言風格和優先級不盡相同。垃圾收集確實帶來了一個巨大的差別:使用 GC 使得 Go 變得更簡單、更小,也更容易理解。而不使用 GC 使 Rust 奇快無比(特別是在您須要保證延遲,而不只僅是高吞吐量的時候),而且得以支持 Go 中不可能實現的特性或編程模式(或者至少在不犧牲性能的前提下是沒法實現的)。
Go 是一種編譯型語言,其運行時獲得了良好的實現,其速度毋庸置疑。Rust 也是編譯型語言,可是運行時要小得多,它真的迅捷無比。在沒有其餘限制的狀況下,我認爲選擇使用 Go 仍是 Rust 其實意味着一種權衡:一方面,Go 的學習曲線更短、程序更簡單(這意味着更快的開發速度);另外一方面,Rust 真的性能卓越,而且類型系統更富有表現力(這使程序更安全,也意味着更快的調試和錯誤查找)。
💡點擊查看 英文原版 文章