毫無疑問,在程式設計語言領域,Go正在成為一顆冉冉上升的新星。由於它在執行效能與開發效率方面都非常出色,正在被越來越多的公司所採用,國外的大公司如Google、Facebook等就不說了,國內的今日頭條、滴滴、小米、七牛雲等都在積極嘗試。
Go的火熱不僅體現在傳統互連網應用中,在新興的區塊鏈領域中也有大量應用,例如以太坊智能合約架構以及商業區塊鏈架構實現Fabric都使用了Go語言。
今天我們就來一起認識一下這位程式設計語言業界的後起之秀。
一. 誕生
Go語言誕生於Google,且它的作者各個都是神一樣的人物:
- 肯·湯普遜(Ken Thompson,http://en.wikipedia.org/wiki/Ken_Thompson):設計了B語言和C語言,建立了Unix和Plan 9作業系統,1983年圖靈獎得主,Go語言的共同作者。
- 羅布·派克(Rob Pike,http://en.wikipedia.org/wiki/Rob_Pike):Unix小組的成員,參與Plan9和Inferno作業系統,參與 Limbo和Go語言的研發,《Unix編程環境》作者之一。
- 羅伯特·格裡澤默(Robert Griesemer):曾協助製作Java的HotSpot編譯器和Chrome瀏覽器的JavaScript引擎V8。
- 布拉德·菲茨帕特裡克(Brad Fitzpatrick,http://en.wikipedia.org/wiki/Brad_Fitzpatrick):LiveJournal的創始人,著名開源項目memcached的作者。
而且,他們大部分都來自於曾誕生了無數電腦科技成果的貝爾實驗室,後來加入了Google。上面介紹中的Plan9就是他們之前在貝爾實驗室的項目,而Limbo語言則是Plan9項目衍生出來的,之後成為了Go語言的前身。
時間回到2007年,那時候Go語言還是上面這幫大佬們在Google閑暇時消遣的一個實驗項目。他們中的很多人是C語言的作者,C語言雖然在很多底層實現中依然有著無可替代的作用,但是C語言畢竟是誕生於上世紀70年代,在21世紀互連網蓬勃發展的今天,C語言並不適合於互連網應用。因此,他們萌生了要開發一款互連網時代的C語言的想法。
2009年,Google發布了Go語言的第一個非正式版本,2012年發布了正式版,截止到2018年5月,已經升級到1.10.2版本了。
不誇張的說,如果說從2007年誕生到今天已經11歲的Go語言是一個意氣風發的少年的話,他出身名門,有著C語言和眾多現代語言的優良基因,從一開始就備受矚目,而今正在大步向前!
二. 設計思想
Go語言的設計目標是要提供互連網時代的程式設計語言,那麼相比傳統的單機應用就要解決如下問題(相對於C語言而言):
並發:C語言雖然也可以提供並發支援,但使用成本較高,今天但網路應用很多都對高並發有著更高對要求,而且伺服器核心數越來越多
大規模分工協作:C語言是一門面向過程的語言,在開發大規模應用時不盡如人意,依賴管理是一件讓人頭疼的事
編程效率:C語言的優勢是執行效率,但是開發效率卻很低,C++和Java等物件導向語言也顯得過於笨重
記憶體回收:C語言需要自己管理記憶體,這是一個門檻很高的技術活兒,很多進階語言如Java早就提供了記憶體回收的完整方案
Go語言期望達到的目標是:
原生支援多核計算核並發
簡單高效的依賴管理,快速編譯和構建
提升開發效率
提供記憶體回收等程式員友好等特性
在實現上述目標的同時,Go語言有一個明顯的設計原則就是:凡是可能帶來困擾又不是特別必要的特性,那就不提供;凡是經常用到的重要特性,提供簡單易用的實現方式。換句話說:對於新特性的新增極為克制,對於常用功能的實現追求極致!
以下試舉幾例:
在Go官方的文檔中關於Go語言為什麼不提供這樣那樣的特性,有這樣一個有意思的說明,或許可以直觀的感受Go語言的設計思想:
Every language contains novel features and omits someone's favorite feature. Go was designed with an eye on felicity of programming, speed of compilation, orthogonality of concepts, and the need to support features such as concurrency and garbage collection. Your favorite feature may be missing because it doesn't fit, because it affects compilation speed or clarity of design, or because it would make the fundamental system model too difficult.
If it bothers you that Go is missing feature X, please forgive us and investigate the features that Go does have. You might find that they compensate in interesting ways for the lack of X.
三. 核心特性
廢話不多說,直接上乾貨:
自動記憶體回收
C和C++靈活的指標和記憶體控制讓程式員可以任意揮灑,感受自由與奔放,彷佛世界盡在掌握,在程式世界裡,你就是上帝,掌握著所有對象的生殺予奪!但這往往也意味著安全隱患,記憶體流失的魔爪隨著準備著伸向我們脆弱的程式。
Java等提供記憶體回收特性的語言可以說徹底的解放了程式員,從此程式員寫代碼就像是進了五星級大飯店,想吃什麼直接拿就是,吃完飯拍拍屁股走人就是,那些擦桌子洗碗的活兒就交給服務員吧。
有著遠大理想的Go語言自然會為程式員提供如此進階的服務了。
函數多傳回值
大多數程式設計語言的函數都只支援返回一個值,如果有返回多個值的情況,通常有兩種做法:
返回一個對象
函數的參數中傳遞傳回值的指標,並在函數中賦值
以上哪一種方法其實都算不上優雅,而Go語言直接支援了返回多個值,像下面這樣:
ip, port := getServerInfo()
匿名函數和閉包
匿名函數和閉包都是動態語言如Javascript,PHP中的特性,可以在一定情境下提供更靈活的表達,提高開發效率。Go對這兩者也提供了很好的支援。
無層級的類型系統
我們都知道在C++和Java等物件導向語言中都支援類繼承,這就會形成一個類的關係樹,如所示:
而在Go語言中,是不支援顯示繼承的,也就是說沒有java中的extends
和implement
關鍵字。但這不意味著Go語言中就無法實現物件導向的繼承,只是說Go換了一種更靈活的方式,也就是非侵入式繼承,簡單來說就是沒有明顯的類層級,同樣實現上面的功能,只需要如下聲明即可:
只要Dog和Cat實現了Animal類中的方法,那麼Go就認為他們是有一定親緣關係的,那麼就可以實現如下寫法:
type Animal interface { eat()}type Cat struct {}func (c *Cat) eat() { fmt.Println("cat eat")}func main() { var animal Animal = new(Cat) animal.eat()}
這樣做的好處主要有以下幾點:
- 介面與類的關係是鬆散的,而不是強綁定的,只要某個類實作類別介面的所有方法,那麼這個類實際上就實現了這個介面,會帶來一定的靈活性
- 使程式員更關注與業務實現,不用花太多時間在介面設計上,甚至可以先實現業務類,再根據需要聲明一個合適的介面
並發
Go語言中引入了一個概念叫做goroutine
,或者叫協程,它是一種比線程更加輕量級的並發單元,只需要使用go關鍵字一行代碼就可以啟動協程。也因此,Go語言在高並發處理方面表現十分優異。有一篇來自國外的關於並發效能的對比,雖然未必能反應Go全部的實力,但是還是可以在某種程度上看出Go的並發效能優勢:每個線程執行一次雜湊運算,5000並發下的不同語言的QPS對比如下:
高效能
Go是一種編譯類型的語言,在運行前會被編譯連結為一個可執行檔二進位檔案,執行效率還是很高的,在權威的效能測試中,很多情境的效能是好於Java的,比python更是好了幾個數量級:
更多對比可以參考這個網站:https://benchmarksgame-team.pages.debian.net/benchmarksgame/faster/go.html
以上就是富二代Go語言的出身介紹了,更多細節,請期待後文。
參考資料
- 許式偉:《Go語言編程》
- https://golang.org/doc/faq#overloading
- https://golang.org/doc/faq#Why_doesnt_Go_have_feature_X
- https://zhuanlan.zhihu.com/p/22486908?refer=study-fe
- https://benchmarksgame-team.pages.debian.net/benchmarksgame/faster/go.html
- https://blog.csdn.net/STFPHP/article/details/72617749
如果喜歡文章內容,可以掃描下面二維碼訂閱作者公眾號,關注作者最新更新,謝謝。