天天看點

go語言的逆襲

Go 語言的哪些特點最吸引您?

并發

Go 最大的特色就是在語言層面天生支援并發,不需要像其他大多數程式設計語言那樣需要開發者自行實作或借助第三方類庫實作并發程式設計,Go 在語言級别支援的并發程式設計,其邏輯簡化得通俗易懂簡單好上手。

性能

不同于大多數腳本或解釋性的高階程式設計語言,用 Go 編寫的代碼直接了當編譯成機器碼高效執行。

簡潔

25 個關鍵字即表達你能想到的所有招式,沒有也不需要有任何多餘,想幹啥事就 go 一下。

跨平台

x86、AMD64 (x86_64)、ARM;Linux、Windows、Darwin (OSX)、FreeBSD、Android (計劃Go 1.4) 幾乎全平台支援,真正做到一份源碼,随處編譯,到處運作。

Go 語言都有哪些常見的應用場景?

作為一個 Go 語言的重度使用者來看,目前除了不适合拿來造作業系統以外在作業系統之上應用級的事情都能幹。再更具體一點,比如說适用于這樣一些使用場景:

系統應用

以前要用 C/C++ 做的系統應用,現在都可以用 Go 來寫,事半功倍,而且 Go 完美包容 C 源代碼,兩者互相調用還可以混合編譯進而無縫內建。

網絡應用

包含了常見的服務端程式設計比如 Web 和 API Service,以前用 PHP / Python / Ruby / Java 幹的事情現在都可以用 Go 更加簡單清晰的來寫。再比如還可以拿來做一些 Proxy(代理)如網絡穿透軟體等,你懂的。

分布式系統

基于 Go 強大的系統程式設計加網絡程式設計,打造各種跨網絡的分布式系統服務,Go 社群有不少和分布式系統相關的開源産物。

各種形态的存儲和資料庫應用

比如 groupcache,influxdb 等。

用戶端應用

包括帶界面的桌面軟體,以及後續可以想像的移動端應用(比如對 Android 的支援)。

雲服務(PaaS)

如基于 Go 打造的七牛雲存儲(分布式對象存儲系統),比如基于 Go 編寫的 Docker(一款開源的容器虛拟化産物)。

Go 能做的事情,包含但不限于以上羅列的使用場景。

Go 語言在七牛中都開發了些什麼服務?在七牛的代碼量中,Go 語言使用占多少比例?

我們主要使用 Go 開發了以下服務和工具:

  • 分布式存儲系統 ( Distributed Key/Value Storage)
  • 資料處理服務 (Data Processing)
  • 網絡接口服務 (RESTful API Service)
  • 消息隊列服務(Message Queue Service)
  • 日志處理系統 (Log Service)
  • Web 網站 (不含前端 JavaScript)
  • CLI 指令行和 GUI 圖形界面工具
  • 其他輔助工具

總的來講,Go 在我們七牛的工程中代碼覆寫率超過 90% 。還有 10% 不能覆寫的原因是我們給開發者自助使用的 Web 界面需要用 JavaScript 程式設計來實作酷炫的前端,以及我們為開發者準備了多達超過 10 種程式設計語言的 SDK 。

Go 有哪些成功的開源項目?都有哪些公司在使用?

Go 比較熱門的開源項目,不完全羅列舉例:

  • docker - 基于 Linux 容器技術的虛拟化實作,能夠輕易實作 PaaS 平台的搭建
  • packer - vagrant 的作者開源的用來生成不同平台的鏡像檔案,例如 QEMU、KVM、Xen、VM、vbox、AWS 等
  • drone - 基于 docker 建構的持續內建測試平台,類似 jenkins-ci
  • libcontainer - docker 官方開源用 Go 實作的 Linux Containers
  • tsuru - 開源的 PaaS 平台,類似 GAE、SAE
  • groupcache - Memcached 作者(Brad Fitzpatrick) 寫的用于 dl.google.com 線上使用的緩存系統
  • nsq - bit.ly 開源的高性能消息隊列系統,用以每天處理數十億條的消息
  • influxdb - 開源分布式時序、事件和名額資料庫
  • heka - Mozilla 開源的日志處理系統
  • doozer - 分布式同步工具,類似 ZooKeeper
  • etcd - 高可用的 Key/Value 存儲系統,主要用于分享配置和服務發現。靈感來自于 ZooKeeper 和 Doozer
  • goandroid - 使之用 Go 編寫動态庫,在原生的 Android 應用中運作
  • mandala - 基于 goandroid 的工具鍊,用 Go 編寫原生的 Android 應用的一個便捷架構
  • beego - 國内 Go 開發者開發的 Web 開發架構
  • revel - 另一個高産的 Web 開發架構,類似 Java Play Framework

更多: https://code.google.com/p/go-wiki/wiki/Projects

用 Go 的公司,不完全羅列舉例:

國外:

  • Google、YouTube、Dropbox、dotCloud、10gen、Apcera、Mozilla、Heroku、Github、Bitbucket、Bitly、CloudFlare、Cloud Foundry、Flipboard、Disqus、SendGrid、Tumblr、Zynga、Soundcloud
  • 更多:https://code.google.com/p/go-wiki/wiki/GoUsers

國内:

  • 七牛雲存儲、京東雲平台、盛大雲CDN、仙俠道、金山微看、Weico、西山居、美團、豆瓣、小米商城、360
  • 更多:https://github.com/qiniu/go/issues/15

在本年度 2014 Androiday.Org 開發者大會上,您有個主題演講提到了 Go 對 Android 的支援,能否與我們分享一下這塊的研究心得?

這是一個很有趣的話題,尤其是在今年6月份相繼召開了 APPLE WWDC 2014 和 Google I/O 2014 兩場舉世聞名的網際網路科技盛會後,APPLE 釋出了用于 iOS 下一代程式設計的 Swift 語言,這給關注 Android 的開發者們留下了無限的遐想,盡管後來驚喜并沒有如人們預期一樣出現。作為一個純潔的 Android 程式員,大概不會關注到 Go 将要支援 Android 的消息;作為一個無邪的 Go 程式員,大概也不會去關心 Android 開發和未來。但戲劇性的就是,我們當下就是處于這樣一個各種跨界的大融合時代,沒有什麼不可能。

由于 Go 是跨平台編譯的,早前就有在 ARM 上編譯 Go 并成功運作的嘗試。這個嘗試是直接将用 Go 編寫的源代碼在 ARM 環境下編譯,然後調用 adb shell 裝入 Android 裡邊作為 Linux 下的可執行檔案運作,但是沒法關聯支援 JNI(Java Native Interface),隻能作為一個獨立的程序運作,然後通過 RPC、TCP 等協定方式通信,相當于是一個 App 在運作方式上分成了兩部分,這樣非常不利于 App 的狀态管理,是以此方式無法用 Go 編寫出無縫結合的 Android 應用。

然而,單方面想要用 Go 語言封裝 Android SDK 更是難以行通的:Android 原本用 Java 封裝的 SDK,包含了海量的 API 接口。如果是手工封裝會導緻功能上的欠缺,自動封裝會讓 Go 語言變得醜陋不堪。不管用哪種方式,都很難快速實作。若是用 Go 再實作一遍 Android SDK 且還想期望能與 Java 等效,這幾乎是不可能的事情。

但實際上,Android 系統提供了兩種開發包:SDK 和 NDK。用 Go 移植 Android SDK 不通,還可以嘗試走 Android NDK 。

Android NDK(Native Development Kit )是一套開發工具集合,允許開發者用像 C/C++ 語言那樣實作應用程式的一部分。然後可以通過 JNI 實作 Java 代碼與 NDK 動态庫的無縫內建。

Go 内置 Cgo,使得 Go 和 C 之間可以無縫地互相轉換和調用,以及代碼混合編譯。僅此一點,就可以看出至少也為 Go 進行 Android NDK 開發奠定了基礎。當然,Go 可以進行的擴充嘗試可可以更多。

後續的嘗試是另辟蹊徑走 Android NDK,借助其可以将動态庫 .so 和 Java 代碼一起打包成 apk 的機制,實作在 Android 上的無縫加載和運作。是以,問題簡化成隻要 Go 能夠編譯出 .so 動态庫再通過 Android NDK 就可以實作開發 Android 應用程式了。

Go 是一門純粹靜态類型的程式設計語言,編譯出來的二進制是靜态的,如何建構動态庫,這是一道坎。不過 Go 社群的欣欣向榮完全超出你我的想像,比如 Go 社群裡邊有人釋出了個開源項目叫 Goandroid,一個擴充了 Go 的工具鍊和運作庫來支援将 Go 代碼建立動态庫(*.so)的工具。另外一個開源項目 Mandala 則是在基于 Goandroid 的工具鍊建構了一套完善的用 Go 開發原生 Android 應用的開發架構。

Goandroid 和 Mandala 的出現已經讓 Go 開發原生 Android 應用成為現實。 盡管這兩個架構都是 Go 社群由個人發起的開源項目,Go 官方尚未參與,不過 Go 已經打開了 Android 的潘多拉魔盒。

另外,可以再來扒一扒和技術無關的業界新聞。

2014 年 5 月,一場已經持續 4 年的官司:關于“Google 在 Android 平台使用 Java 侵犯知識産權”一案,聯邦法院判定 Oracle 獲勝。

2014 年 6 月,APPLE 公司在 WWDC 2014 上釋出 Swift 程式設計語言,用來替代 Objective-C 更高效地編寫 iOS 和 OS X 程式。

2014 年 6 月,Google 公司 Go 語言開發團隊成員 David Crawshaw 提議下一個 Go 版本 ( Go 1.4 ) 支援 Android 平台。這算是一個關于 Go 支援 Android 而言相當擲地有聲的宣稱。文獻詳見:http://golang.org/s/go14android

就目前而言,Go 支援 Android 後可以幹啥。簡單來講,Go 以支援 Android NDK 程式設計作為切入點,自然是可以在 NDK 這層注入 Go 所能帶來的新鮮活力,比如在異步的并發程式設計上用 channels 而不再是 callbacks 通訊,比如為遊戲引擎提供底層的高性能支撐,比如跟多媒體相關的更豐富地處理。是以,可以想像的到 Go 是可以引領 Android NDK 迎來一片生機盎然的春天。

Go 支援 Android 這事目前看起來是 Go 的一廂情願,而 Android 對此結合似乎還無動于衷。然而, Android 背負的包袱畢竟過重。Go 躍出的一小步,開啟的必然會是 Android 海闊天空的一大步。

談談您個人對 Go 語言的了解和看法?

盡管 Go 是一門問世不久顯得很新的程式設計語言,有很多質疑的聲音認為新生的事物就是不成熟就此望而卻步。但在我個人看來,考量成熟的因素并不完全取決于它所經曆和走過的歲月,而是在于它是否可以被當下這個時代所需要并賦予厚望,以及其心智和能力是否能夠承載并擔當得起這份榮耀與責任。

在我們今天這個時代,是一個包含了 PC 網際網路、移動網際網路、物聯網和雲計算 “四世同堂” 的技術多元盛世。在不曾久遠的過去,此前的數十年間,沒有哪一門程式設計語言能夠經得起此般歲月的幾經摧殘而長生不老。70 年代就開始基業長青的 C,書寫了整個單機時代的輝煌,在硬體更新換代多核一度再翻成指數級更疊又如此瞬息萬變的今天,C 那副認真憔悴的注目神情所表達的靜靜默守和激流勇退才終歸得以明白它曾有過的卓絕。而 Java / Python / PHP / Ruby 此前彼後所縱橫的 PC Web 時代,以當下之勢在此不可逆轉的時代背景下正似歲月如梭般地離我們漸行老去。而當移動網際網路悄然踏至的那一時刻,Android 勢如破竹般地野蠻生長搭救了 Java 一命并在其身上傾覆了所有,換來的卻不過是一份難以割舍又無法言痛的沉重愛情,在被包養換主後的 Java 擦傷了貞潔之後不得不忍辱負重潸然淚行,而 Java 也從此難以走下一座叫作 “節操” 的斷背深山。而和 Java 長得很像極帥的那位 JavaScript,意氣風發一竿子捅到底逆襲了整個 Web 後端,讨得所有 Web 前端開發者的擁簇和狂歡,眼看高舉全棧工程大旗就要翻手為雲覆手為雨,卻優秀得不懂克己錯失風向與當下這個多核時代格格不入,曾一度與 HTML5 結隊合唱 “輕應用就是未來” 這一出雙簧,不料 Apple Swift 以迅雷不及掩耳之勢以逆襲之道還治其逆襲之身;如今既生 Go,又何生 NodeJS,感慨 Node 君真是生不逢時。總之,問君能有幾多愁,掐指一算,不知諸君該何去何從……

雖群雄逐鹿,現百家争鳴,然亂世必有新生。 Go 有如清水出芙蓉,一個曾在溫柔的歲月裡深沉熟睡,爾後随着換季時節的輕聲絮語呼喚蘇醒,然後起身刹那之間不經意驚豔了時光,此後就在此應時之季嬌豔綻放,随後波光花影,激蕩漣漪,滿是春意盎然,勃勃生機。

時光往回倒流近二十年,那是 1995 年,有幾位計算機泰鬥,在白紙上畫了一個圈,開啟了分布式系統程式設計時代的春天。那時還在貝爾實驗室參與九号計劃(Plan9)的 Robert C. Pike(Plan9 作業系統和 UTF-8 的共同設計者,分布式程式設計語言 Limbo 作者) 和 Kenneth Lane Thompson(1983年圖靈獎得主,建立了 UNIX 和 Plan9 作業系統,B 語言和 C 語言的共同設計者,UTF-8 的共同設計者),在此段工作經曆中開發了分布式網絡作業系統 Inferno,并在此之上實作了分布式程式設計語言 Limbo,這是能夠追溯到最早和後來的 Go 在功能特性上比較相似的前身。随後這兩位泰鬥相繼都加入了 Google 公司,在 2007 年 9 月,這兩位 Unix 和 C 還有 UTF-8 的始祖成員,再加上 Javascript V8 引擎和 Java HotSpot 編譯器的作者 Robert Griesemer 一起,這 3 人小組設計了最初的 Go 語言雛形。此後,Go 語言逐漸吸引了一些業界優秀人物比如 80 後程式員 Brad Fitzpatrick(Memcached 作者,OpenID 協定者)的加入,Go 的團隊陣營逐漸壯大。從 2007 年 9 月作為一個 Google 20% 自由時間的一個實驗項目;到 2008 年 5 月發展為 Google 100% 支援的全時項目;再到 2009 年 11 月;Google 首次對外公開透露 Go 的存在;以及 2012 年 3 月,Go 1.0 官方正式版問世;Go 的演變和發展簡直始料未及,從開始到現在都是一如既往地突飛猛進,一發不可收拾。

如果說到 Java 曾經的流行,我們會聯想到 SSH(Struts + Spring + Hibernate);如果提到 Python,也會聯想到 Django;如果提到 Ruby,會聯想到 Ruby on Rails;如果提到 JavaScript,會聯想到 NodeJS;如果提到 PHP,更是一堆長江後浪推前浪前浪死在沙灘上的 Web 開發架構。這些程式設計語言社群的繁榮昌盛無一例外都和 Web 開發息息相關,且最終沉澱下來的都是各種五花八門各有千秋的衆多 Web 開發架構。可以說,我們目前所面臨和 Web 開發的技術選型,從未有過如此的繁榮。繁榮的背後,襯托的是一個大江東流去不複還的 PC Web 時代。

我們再來看看 Go 的社群,是多麼地非同尋常和多樣豐盛。我們之前列舉過 Go 社群裡邊比較流行熱門的開源項目:比如 Docker,是時下最流行和容器虛拟化相關的技術産物;比如 GroupCache ,是一個類似或代替 Memcached 的分布式記憶體緩存系統;比如 nsq,是一款處理海量并發的消息隊列系統;再比如 etcd,是一套用于配置同步管理的分布式鍵值存儲系統;以上這些都是和網絡和系統服務以及分布式相關。再比如 Goandroid,是一個開發 Android NDK 應用的工具,是和移動開發相關的…… 總之,有太多創新的開源産物,而 Web 開發架構都不是主要重點。Go 幾乎涵蓋了和程式設計領域相關的所有點和面,在 Go 1.0 正式版出現後的兩年時間裡,基于 Go 可以枚舉全面覆寫的開源項目超過了 1000 個。可謂是随風潛入夜,潤物細無聲。

從 Go 誕生的時代背景和團隊陣容以及開源社群的繁榮來講,Go 并不是新生不熟,而是後生可畏,且極有可能成為一統天下的集大成者。

我們再來看一些實際使用場景,比如 Web 開發。大多數程式設計語言之上的 Web 開發架構都是遵照 MVC 的處理流程去開發 Web 應用:Model 部分封裝資料,Controller 部分處理業務邏輯,View 部分植入變量填充模闆頁面。而大部分 Web 架構關于 MVC 的三部分都是在 Server-side 處理,比如對 View 部分的處理都是在 Server-side 通過程式動态對模版變量求值後再拼接組裝成 HTML 頁面輸出給浏覽器去呈現。而 Go 開發 Web 應用,并不依賴任何 Web 開發架構,用内置的标準庫就可以輕而易舉地實作:比如使用 

net/http

 标準庫就可以數行代碼建構一個完整的 Web 骨架應用;再比如,通過關鍵字 

struct

 封裝一個資料結構就可以表達原本 MVC 架構中需要用厚重的 ORM (Object-Relational Mapping) 才能表達的那部分。大道至簡,這可以說是 Go 的哲學。在 View 這一層,Go 也有相應标準庫提供支援,但更推薦的做法,是當下比較流行的 MVVM (Model-View-ViewModel):Server-side 隻輸出 JSON,浏覽器 DOM 作為 View 層,前端 JavaScript 充當 Contoller 部分;這樣,不僅減少了 Server-side 的資源消耗還有中間傳輸的網絡流量,而且前端可以更靈活和更豐富,後端也可以更輕盈和更高效,也更有利于項目的分工和協作。 而 Go 對 JSON 的生成和輸出,有資料測試表明異常高效(在 i7-2600K 處理器上針對所有程式設計語言包含開發架構總計約100個測試對比中,Go 的性能名額穩居第一,詳見:http://t.cn/RvZHyKI)。以我個人喜好之見,後端用 Go 前端用 AngularJS 可以說是現今流行 MVVM 方式的 Web 開發之絕唱組合。是以,如有疑問 Go 适不适合用來做 Web 開發,我想答案很肯定的:不但可以而且更簡單同時做得更出色甚至還可以做的更多。

我們再來看看當下硬體突飛猛進的多核時代,軟體層面的程式設計語言都有哪些支援和作為。“人生苦短,我用 Python”,被喊了這麼多年的智語,是有多少有追求和品味的程式員都熱衷于 Python。我想大家可以做個實際測驗:比如用 Python 寫一個死循環程式,然後運作起來,過一小段時間看看 CPU 占用率是多少。測試結果會是什麼呢,CPU 會占用 100% 嗎?不好意思如果是那應該是單核,且還得是沒有超線程支援的骨灰級 CPU 才行!在當下普遍的雙核(甚至 4 核或 8 核) CPU 上,這個死循環跑滿最多隻會占用不超過 50% 的 CPU 資源。好吧,你會說我開多個線程并行來跑這個死循環不就可以吃滿 CPU 了嗎?我想測試結論可以很明确的告訴你,多線程的方式并行跑這個死循環可是連 50% 的 CPU 都吃不到,不信你可以試試,呵呵。無需我解釋為什麼,大家可以自行 Google 搜尋看看 GIL (Global Interpreter Lock) 機理。也不是我特别拿 Python 舉例,PHP / Ruby / NodeJS 的程式員們也可以來做做同樣的測試,呵呵。總之,一個簡單得不能再簡單的死循環,程式上再怎麼優化,跑起來都吃不滿 CPU,你說我們都是這麼有品味的程式員,到底都是在追求些什麼呢?這些 PC Web 時代下的腳本語言或者位元組碼解釋型的語言,幾乎都由于線程安全問題而在語言級的并發機制上裹足不前。盡管 Ruby 實作了很華麗的纖程,NodeJS 實作了很光線的非阻塞 IO,但始終逃離不了單線程簡單可依賴原則抑或多線程效率提升但伴随着各種問題困擾進而不得不折中取舍的桎梏。是以,大部分時候,語言層面沒有根本性地解決并發問題,轉而使用傳統的多程序這一外援政策去解決并發需求以及變相地迎合這個多核時代。然而,硬體很快,軟體很慢,摩爾定律在硬體行業的應驗帶給傳統軟體行業的紅利已經走到了盡頭。

我們再來看看 Go 在當下這個多核時代的作為。不得不說,Go 最大的特色就是在語言層面天然支援并發,在 Go 程式裡邊,你可以通過在⼀個函數調用前使用關鍵字 go 即可讓該函數 func 運作成為一個獨立的 goroutine,goroutine 可以了解成一種比線程更加輕盈更省開銷的輕量級協程。Go 的并發模型就是通過系統的線程來多路派遣這些獨立函數的執行,使得每個用關鍵字 go 執行調用的函數可以運作成為一個機關協程。當⼀個協程阻塞的時候,排程器就會自動把其他協程安排到另外的線程中去執行,進而實作程式的無等待并行化運作。且排程的開銷非常小,單核 CPU 排程的規模不下于每秒百萬次,這使得我們能夠建立大量的 goroutines,進而可以很輕松地編寫并發程式達到我們想要的目的。

同時,Go 在語言層面還引入了 channel 這一内置類型來實作并發執行體 goroutines 之間的消息傳遞,通信靠 channels 來傳遞消息。Go 遵循 CSP(Communicating sequential processes) 并發模型,通過通信來共享記憶體而不是用共享記憶體的方式進行通信。Go 的并發裡邊沒有共享記憶體,更沒有記憶體鎖,這⼀切都有利于進行更為安全和簡單的并行程式編寫。

終有一日,你會感慨:“人生苦短,說 Go 就 Go”!

時代在快速躍遷,尤其是現在言必及多核和并發,我們所看到的那些 PC Web 時代下的腳本語言所堆砌的華麗不過是一些延續性追随,而且這種延續性的步伐會越來越沉重,最終還是苦不堪言。唯有 Go,在語言層面對并發和多核乃是純天然的支援,原本就是一場應時而生順時而為的土生土長,Go 所代表的是一種破壞性創新。而我們所經曆的這個時代,正是處于一個時代被時代所颠覆的時代,在這樣一個轉折點,所有的延續性創新不過是杯水車薪,唯有破壞性創新,與時代共舞,才會産生革命性的颠覆。

我們還可以回顧下之前提到 Go 對 Android 移動端非侵入式的支援,幾乎就是一場悄無聲息的逆襲。

Go 很年輕,卻已健壯成年。Go 被設計得簡潔高效,Go 在文法層面有着清晰簡潔卻又高效的表達能力,是一個讓開發者編寫程式很開心同時又更有生産力的系統程式設計語言。Go 在語言層面有着良好的并發支援,使得用 Go 語言編寫多核和分布式網絡的應用程式簡單容易許多。Go 内置新穎靈活的類型系統還可以很友善地編寫和構模組化塊化程式。Go 是一門需要編譯源碼才能運作應用的純靜态強類型語言,這點保證的了程式的安全性和執行效率,且 Go 從程式源代碼編譯成機器碼非常快。Go 的跨平台支援,使得用 Go 語言編寫的程式可以在現今大多數作業系統上編譯運作。Go 還自帶垃圾回收的記憶體管理機制,并且支援強大的運作時反射。Go 是動靜相宜的,在性能和安全性方面保留了靜态語言的優點,在程式設計寫法上,卻有着動态語言的靈活與優雅。

Go 是劃時代的,唯有 Go 能成為史詩之絕唱!Go 不是在颠覆,就是在逆襲!