「GCTT 出品」gogeof 曾經的 Go 程式設計師又回來了

「GCTT 出品」gogeof 曾經的 Go 程序員又回來了

按照慣例,第一篇博文總要說點歷史,對吧?我作為軟件開發人員,主要還是使用 PHP 語言。第一次接觸它還是我在高中的時候,跟一個朋友一起開發一個項目。我們想為項目建一個網站,正好發現一個用 PHP 語言,代碼寫得非常整齊,並且預打包的解決方案。那個時候,我完全不懂這些代碼是幹嘛的,也沒有花時間去弄懂它。多年之後,我再次與 PHP 相遇。在我進入大學的前 6 個月(我想大約 7 年前),PHP 成了我主要關注的語言之一。兩年前,我第一次經人介紹瞭解到 Go 語言。

我大部分專業經歷都來自於位於利茲中心的代理機構。這是一個夢幻般的公司,我從中學到了很多,因為很早我就被給予了很高的自由度。我為一個範圍很廣的項目工作:標準的 CMS 構建,定製 API 接口,手機應用程序,為了提高效率的自動化,部署和基礎架構設計,以及其他很多功能。

在代理機構的這段時間裡,我和一個我們聘請的實習生成為了朋友。他真的是個天才,也是他突然向我介紹 Go 語言。我說我會試試,然後說一下我對它的看法。很快,我就覺得我喜歡上它了。跟 PHP 相比,更好的性能,類型安全,支持併發,本地編譯後的二進制文件,相當小,啟動速度相當快,這非常地誘人!如果你從 PHP 轉 Go 開發,那麼會有一大堆讓你感到激動的東西。

奇怪的是,我其實並沒有那麼喜歡它。我認為它的語法很怪,它的工具還好,但處理錯誤是如此地繁瑣,(甚至,)天哪,地球上怎麼還有像 Go 語言這樣沒有支持泛型的語言?我記得與這位實習生進行了很多類似的對話,他可能告訴我所有我後來自己也慢慢意識到的事情,但是我繼續尋找新的東西來學習 PHP 以外的東西,現在改為 Go 語言也是這樣。

使用 Scala 的一年(The Year of Scala)

我的搜索很快把我帶到了 Scala 的世界。如果你沒怎麼聽過 Scala 的話,它是運行在 JVM 上的函數編程語言。當時很有吸引力的一點是 JVM 很快(一旦啟動並運行起來之後),函數式編程當時瘋狂地席捲了編程界。

我迷上了 Scala,花了一年時間圍繞著它,學習它的語法。當我愛上它時,儘管編譯時間比 Go 長,但使用 SBT 的工具實際上也沒有那麼糟糕(得益於增量編譯)。我學習其語法,花了一些時間之後,就能像編寫 Java 一樣編寫 Scala,而且使用的語法還更少一些。接下來,我專注於學習函數編程原理,如更純粹,引用透明性,不修改狀態(等函數式編程的原則)。在編寫 PHP 時,我曾遵循過許多這裡描述的原則,但並沒有想過要如何編寫一個純函數式的應用程序。

在我使用 Scala 的過程中,我大量閱讀了相關博客,閱讀了一些 Scala 社區裡比較流行的書,參加 Martin Odersky 使用 Scala 函數式編程的課程。我覺得我不能只是待在我能做出有用的東西的地方。我應該待在可以提高在 Scala 項目工作的機會的地方,我對自己的 Scala 技能應該有足夠的信心,我應該能為這樣的項目工作。然而情況卻是…我並不這麼覺得。我還是覺得其他人的代碼很讓人迷惑,很難閱讀。覺得其他人寫的每一個庫都有自己不同的(編程)風格,並且還需要學習大量的詞彙。我瞭解一些廣泛被使用的庫,像 cats 和 shapeless,但還是不明白它們幹了什麼或者為什麼你需要它們。

回過頭來,不要誤解我的意思。Scala 是一門令人印象深刻的語言,我非常尊重那些使用這門語言工作的人。它本身沒有任何限制,這是好事也是壞事(對於我來說,是壞事)。我喜歡類似於保持不變的想法,難以置信的是編譯器撿起了類型錯誤。這非常罕見,它丟掉了重要的東西,並讓錯誤可以在運行時發生。

我確實用 Scala 做了一些事情,但也弄得我越來越沮喪。我曾想解決我想解決的問題,但總是因為各種原因弄得焦頭爛額。要麼就是我缺乏函數編程的經驗技巧,要麼就是像 JVM 啟動時間這樣的事情讓我感到沮喪。不知道為什麼,我在這一年後仍然發現還有 Scala 的新語法(需要我去學)。我覺得我已經在這條路上走了一年,但收穫甚少。

重回 Go 語言(Back to Go Again)

在使用 Scala 一年以後,我決定再給 Go 一個機會。(因為)我發現沒有其他的語言能像 Go 一樣在方框中打這麼多勾,使用 Scala 的一年只是讓我增加更多的方框來打勾。這些方框都有什麼呢?

  • 快速編譯:雖然 SBT 增量式編譯在開發時可以加快編譯速度,從頭開始編譯還是需要花費很長的時間,而且即使是 SBT 增量式編譯,花的時間也比 go build 花的時間長。
  • 快速啟動應用:我對於開發 CLI 工具非常感興趣。早期使用 Go 和 Scala 語言開發的庫中都有一個為了創建 CLI 應用的庫。這對於用來測試不同語言開發的應用的啟動速度非常有用。
  • 低內存佔用:我並不是研究 JVM 直接使用多少內存的狂熱粉絲。但我也知道如果我想將我做的事情 Docker 化,對於今天的 JVM 來說還是個問題。
  • 功能豐富,風格一致,但簡單的標準庫:Scala 擁有大量的庫,但你可以發現(其實)大量依賴於 Java 庫。有一些並不是那麼令人愉快。最重要的是,當你開始引入這些依賴關係時,心裡就會開始覺得(為啥)你不得不下載整個互聯網來做一些非常基本的事情。
  • 編譯時類型檢查:Scala 在這方面表現出色,但多數情況下,你需要犧牲可讀性作為代價。在某些情況下,Go 會漏掉一些編譯時的類型檢查,但這種情況非常罕見,因為通常有其他可以在編譯時做類型檢查的解決方案。
  • 垃圾收集和類型安全:我不想接觸太低層的東西,但我還是想比我使用 PHP 時能對應用程序幹什麼有更多的控制。
  • 內嵌的併發原語:來自於 PHP,這是我想更多解釋的地方。使用 Scala 開發程序時,我有機會用上併發,但從來沒有像使用 Go 一樣對應用程序能控制得這麼多。
  • 廣泛採用的編程風格約定:來自於 PHP,PHP 標準建議(PSR)相當流行,我知道我喜歡擁有能夠到處使用的代碼風格約定的語言。我相信很多語言都能從中受益,包括 Scala。
  • 對於我來說,Go 符合所有這些要求,甚至更多。我認為 Go 給了你很多可以開箱即用的東西。你也可以在其他地方找到這些東西,但並不像 Go 一樣全,而且整潔。

開始激怒我的一些 Go 的特性也變得可以接受了。我覺得我最終明白了一些東西,像 Go 語言一樣,也需要

作出一些妥協;以確保像上面的那些框可以被打勾。為了你可以得到更多的好處,另外一些地方就得難受一點,但有一點非常清晰,語言總體上被設計成最大化開發生產效率。錯誤控制就是個很好的例子。它很繁瑣,有時它有一點不是那麼有用。然而,它讓函數里面哪裡會發生錯誤變得非常清晰,這意味著,當你閱讀別人代碼的時候,你能夠清楚地知道什麼時候,或者為什麼錯誤會發生。

另外一個可以做出這個判斷的,開始時令我感到困惑的是 context 包。我本來並不是很喜歡它,並且認為它處理問題用了一種非常冗長的方式。為什麼我們不能直接殺掉 goroutines 呢?context 跟錯誤非常像,它的冗長也是顯式的,告訴你某個給定代碼的某些內容很可能在某些時候被取消。你不能殺掉 goroutine,因為你沒辦法處理它產生的 goroutine?畢竟他們不再是孩子。

約定,工具使得 Go 語言開發的項目令人難以置信地一致。到當前為止,比我用過的任何語言都要好。當你有像 goimports 和 gometalinter 一樣的工具,就不奇怪每一個項目都有相同的代碼風格,甚至相同的文檔風格。工具也能幫助你避免代碼中相同的 bug 和減少誤解。

我開始用 Go 寫軟件後,覺得最棒的是,我可以真正解決問題了。我想解決的實際問題,不僅僅是一些隨機的數學教學問題。最近一段時間(我希望可以寫得很快),我在製作一些工具來幫助自動化我的 Arch Linux 桌面的一些地方。我寫了一些工具去管理我的工作區,為一些東西顯示通知,做一些像自動配置我的顯示器(都是一些解決桌面環境的問題,但它是一切工作的開始)。

學習 Scala 時,對於一些數學問題,我建議創建的解決方案非常有意思,但卻(糾結於)沒能寫出解決實際問題的軟件,直到使用 Go 語言才釋然。這不是 Scala 的錯誤,它確實能夠解決問題。我知道這是一個巨大的範式轉變,鑑於我的歷史,我將需要一個很大半徑的彎曲學習曲線。對於我來說 Go 沒有學習門檻;實際上 Go 本來壓根就沒有學習門檻。沒有很複雜的編譯工具,語法可以一下子裝進你的腦裡,你能很快上手。可能你從第一天開始就可以閱讀別人的代碼,包括閱讀標準庫中的代碼。

Go 語言不是完美的,但它在不斷完善中。我對這門語言的未來感到非常興奮,並且從中看到了我想要的東西。


分享到:


相關文章: