如果讓我推薦編程語言的話(一)

作者:池建強

原文鏈接:如果讓我推薦編程語言的話(一)

早期經常有人問我學習編程語言應該從哪一門入手,我一般會推薦 Java 和 Python,這兩門分屬靜態語言和動態語言,應用廣泛,上手方便,上能九天攬月,下可五洋捉鱉,能寫出小工具小網站,也構建出世界級的大型互聯網帝國,比如淘寶,比如豆瓣。我一般很少推薦 C 或者 C++ 這種前進的路途上密布荊棘和陷阱的語言,人還沒看到鮮花,可能已經從入門到放棄了。

現在會有人問我,投資自己的時間去學習最有價值和前景的編程語言,你會推薦哪些?以我個人拙見,我會推薦 Go、Python、Lua 和 JavaScript。

世間沒有無緣無故的愛,推薦當然也有理由,比如 Go 在伺服器端強大的並發處理能力,優雅的類型設計和簡潔的語法。推薦 Python 是因為這門古老的語言在大數據和機器學習時代重新煥發了生機,幾乎所有頂級的機器學習項目,比如 TensorFlow,都優先把 Python 作為第一支持的語言。推薦 Lua 是因為 OpenResty 的崛起,大部分互聯網應用都會涉及到伺服器端的負載和連接能力,這方面 Lua 有著得天獨厚的能力,目前 OpenResty 創始人章亦春已經開始提供基於 OR 的商業化解決方案,未來,也許可以用 Lua 構建大部分業務系統呢。至於 JavaScript,據說前端開始統治世界了,他們手裡的屠龍刀就是這門語言。

今天閑話一下 Go 吧,希望能寫個小系列。

以前開玩笑總說 Go 站在編程語言鄙視鏈頂端,鄙視其他所有語言。關於這一點 Lisp 是不服氣的,因為 Lisp 是編程鼻祖,PHP 也是不服氣的,因為 PHP 是世界上最好的語言。但我這麼說也不是沒有道理,因為 Go 「世出名門,雍容華貴」,具備正宗的編程血統。使用 Go 語言編程的程序員們都像手拿 AK47 的企鵝,雄赳赳,氣昂昂,殺進互聯網。

什麼名門呢?

2009年,世界上最大的互聯網公司 Google 推出了一門新的編程語言 Go,也叫 Golang,這是一門靜態類型、編譯型、並髮型並具備垃圾回收機制的編程語言。這門語言的三個設計者對於程序員來說如雷貫耳,他們分別是:

Robert Griesemer:曾協助實現 Java 的 HotSpot 編譯器和 JavaScript V8 引擎。

Rob Pike:曾是貝爾實驗室的 Unix 團隊和 Plan9 操作系統成員,與 Thompson 一起創造了 UTF-8 字元編碼。

Ken Thompson,不用多說了,技術聖殿的人物,創造了 C 語言和 Unix,獲得了 1983 年圖靈獎和 1988 國家技術獎。

據說這些大神們創建 Go 語言的初衷是:近十年來開發程序之難讓我們有點沮喪。於是 Go 誕生了。

Golang 是一門全新的、現代的、語法簡潔並容易上手的編程語言,它不像 Scala 或 JRuby 這樣的語言,要依附或脫胎於其他平台或語言,而是拋開歷史包袱完全重新設計的、致力於充分發揮現代硬體性能的一門工程語言,具備獨立的運行時庫,就像 C 語言一樣。

C 語言的強大勿用多言,但我們不得不承認,C 是一門既簡單又極度複雜的語言,以至於你每寫一行代碼,都能想像出編譯後指令的執行,堆棧的分配,C 充滿了太多不著邊際的規則,程序員如同行走在黑暗的森林裡無所適從。Go 就好得多,語法關鍵字和控制語句都做到了最簡模式,並且規則嚴謹,少有歧義,不像 Ruby 那樣可以寫出各種「奇技淫巧」的黑魔法代碼。無論是高手還是初學者,大家寫出來的代碼都差不多,如同太祖長拳,在普通拳師和喬峰手裡,威力大不相同,但招式都差不多。這是簡單的本質。

Go 語言的 Hello World 是這樣的:

package mainfunc main() { println("Hello, World")}

寫一段非同步執行的程序也非常簡潔,比如在執行程序的時候你想非同步記錄一些日誌:

func log(msg string){ ...}go log("Bad things happened...")

Go 語言簡化了自增和自減運算符,保留了指針,把切片(slice)和字典(map)作為內置類型,從運行時層面進行了優化,保證了語言的簡潔和容易使用。

其並發模型是使用 Go 編碼的程序員們最喜歡的特性之一。到了多核的時代,並發編程差不多成了程序員必備技能。哪一種並發模型更好?Java 的 ForkJoinPool,還是 Erlang 的 Actor + Message,還是 Objective C 的 Grand Central Dispatch:Block + Queue,亦或是 Hadoop 的 MapReduce……最終 Go 推出了自己的並發模型 goroutine 和 channel。

大部分非同步模型都是顯式的,一旦要開啟非同步模式都會大喊一聲,閃開,我要創建線程了,並配以明顯的出場標誌(比如披風和外穿紅色內褲)。Go 就低調的多,它通過類協程的方式處理並發單元,從語言層面對並發編程提供支持,比如 go log(…) ,這條簡單到二爺都能看懂的代碼已經默默的完成了所有非同步功能,低調的就像日理萬機而又默默無語的安姐(她幫別人解除焦慮的起始句是:我19歲大學畢業的時候……聽完大家都焦慮了)。

與 Erlang 相比,Go 並沒有實現嚴格的並發安全,允許全局變數、指針等共享內存,這就需要編程人員自行維護數據的一致性和完整性,於是引出了 channel 的概念。channel 實現了 CSP(Communicating Sequential Processes) 模型,各個並發單元間的數據解藕了,我們可以通過 channel 在兩個或多個 goroutine 之間傳遞消息,我們認為 cahnnel 是一種類型安全的管道,數據和消息在其中自由流轉,安全並且順暢。

Go 語言的編程模型大大提升了伺服器端的處理能力,我們可以輕鬆構建出 C100K 這樣的高性能伺服器,甚至處理更多的請求。

Go 語言採用 tcmalloc 方式進行內存分配,tcmalloc 是一套針對高並發的內存設計的組件,Go 的內存分配器完整保留了 tcmalloc 的原始架構,確保了在高並發壓力下能優秀的完成內存分配任務。在最近的幾個版本,Go 的編譯器做了很大的改進,它儘可能把對象分配在棧上,以降低垃圾回收的壓力,減少消耗,提高性能。

說到自動垃圾回收,算是 Go 的一個痛點,關於這一點,Java 是先行者,不過也被低效的垃圾回收策略拖累了很多年。Go 面臨的問題更複雜一些,因為指針的引入,需要垃圾回收演算法更加精確有效。網路和生活中遇到垃圾人,我們可以不理,但程序產生的內存垃圾不回收,會有系統宕機的危險。Go 最初採用的是標記清掃演算法,到了 1.5 開始引入三色標記和寫屏障,垃圾回收的性能才有了好轉。這套機制最終的目標就是在用戶業務無感知的情況下實現垃圾回收,希望未來的版本這部分有更優秀的表現。

閱讀原文


推薦閱讀:

如果編程語言是女孩,你會選擇哪一個?
如何最快速的提高閱讀英文技術文檔的能力?
世界範圍內,有哪些用 Ruby 開發的優秀網站?
生命周期標記
內部可變性

TAG:编程语言 | Go语言 |