先來(lái)聊聊go有趣的歷史
在google中,大部分的項(xiàng)目都是采用C C++開發(fā),少量地用了java,其次 才是python;在2007年的某一天,google的首席工程師在編譯一個(gè)C++項(xiàng)目 過(guò)程中,盡管在google早就實(shí)現(xiàn)了分布式編譯系統(tǒng),但是Rob Pike和Robert Griesemer實(shí)在受夠了那個(gè)漫長(zhǎng)的編譯等待時(shí)間,于是突發(fā)靈感與坐在旁邊的 Ken Thompson一起討論實(shí)在有必要發(fā)明一個(gè)新的編程語(yǔ)言,這個(gè)編程語(yǔ)言必 須有近乎C語(yǔ)言的執(zhí)行效率和近乎解析型語(yǔ)言的開發(fā)效率,以及近乎完美的編譯 速度,于是他們?nèi)∶@個(gè)語(yǔ)言為go語(yǔ)言,就如每一個(gè)go語(yǔ)言的使用者都成為 gopher,gopher是一種生活在加拿大的小動(dòng)物,它的中文名叫做囊地鼠,這 種動(dòng)物有個(gè)特點(diǎn)就是生活在底下,哈哈,當(dāng)然這個(gè)不是最關(guān)鍵的,他們最大的 特點(diǎn)就是挖洞速度特別快,當(dāng)然可能不止是挖洞啦,取名為go意為語(yǔ)言的運(yùn)行 速度、開發(fā)速度、學(xué)習(xí)速度(develop)都像gopher一樣快。

被稱為GO語(yǔ)言之父的Rob Pike說(shuō),你是否同意GO語(yǔ)言,取決于你是認(rèn)可 少就是多,還是少就是少(Less is more or less is less)。Rob Pike以一種非常 樸素的方式,概括了GO語(yǔ)言的整個(gè)設(shè)計(jì)哲學(xué)--將簡(jiǎn)單、實(shí)用體現(xiàn)得淋漓盡致。
很多人將GO語(yǔ)言稱為21世紀(jì)的C語(yǔ)言,因?yàn)镚O不僅擁有C的簡(jiǎn)潔和性 能,而且還很好的提供了21世紀(jì)互聯(lián)網(wǎng)環(huán)境下服務(wù)端開發(fā)的各種實(shí)用特性,讓 開發(fā)者在語(yǔ)言級(jí)別就可以方便的得到自己想要的東西。
強(qiáng)大的研發(fā)團(tuán)隊(duì)
go的應(yīng)用
使用go語(yǔ)言開發(fā)的開源項(xiàng)目比較著名的主要有:
Docker,火熱的容器化技術(shù); Kubernetes,Goole Borg的開源實(shí)現(xiàn); Etcd,類似zookeeper的高可用key-value存儲(chǔ); TIDB,國(guó)人開發(fā)的Google spanner的開源實(shí)現(xiàn);
許多大廠都已經(jīng)擁抱 Go 語(yǔ)言,包括以 Java 打天下的阿里巴巴,更別提深 愛(ài)著 Go 語(yǔ)言的滴滴、今日頭條、小米、奇虎 360、京東等明星公司。同時(shí), 創(chuàng)業(yè)公司也很喜歡 Go 語(yǔ)言,主要因?yàn)槠淙腴T快、程序庫(kù)多、運(yùn)行迅速,很適 合快速構(gòu)建互聯(lián)網(wǎng)軟件產(chǎn)品,比如輕松籌、快手、知乎、探探、美圖、獵豹移 動(dòng)等等,更比如前不久泄漏的B站后端源碼都是采用go語(yǔ)言開發(fā)。
從業(yè)務(wù)維度看,在云計(jì)算、微服務(wù)、大數(shù)據(jù)、區(qū)塊鏈、物聯(lián)網(wǎng)等領(lǐng)域,Go 語(yǔ)言早已蓬勃發(fā)展。有的使用率已經(jīng)非常之高,有的已有一席之地。即使是在 Python 為王的數(shù)據(jù)科學(xué)和人工智能領(lǐng)域,Go 語(yǔ)言也在緩慢滲透,并初露頭 角。
go的特性
并發(fā)與協(xié)程
基于消息傳遞的通信方式
豐富實(shí)用的內(nèi)置數(shù)據(jù)類型
函數(shù)多返回值
defer機(jī)制
反射(reflect)
高性能HTTP Server
工程管理
編程規(guī)范
為什么要選擇go語(yǔ)言
你為什么選擇這門語(yǔ)言去開發(fā),關(guān)于這個(gè)話題,永遠(yuǎn)是爭(zhēng)議最大的,比如 程序員鄙視鏈,但是我在開講go語(yǔ)言之前還是要來(lái)趟這個(gè)渾水,如果有失偏頗 的話,還請(qǐng)海涵。首先存在即合理,那么多的計(jì)算機(jī)語(yǔ)言存在,都會(huì)有其時(shí)代 背景和對(duì)軟件工程中某些特殊問(wèn)題的解決,不能一棍子敲死,比如C/C++牛 逼,那為什么java的應(yīng)用范圍非常廣,java程序員的數(shù)量多過(guò)C/C++,java看 起來(lái)被這么多人如此使用,那為什么現(xiàn)在越來(lái)越多的企業(yè)轉(zhuǎn)向用go語(yǔ)言開 發(fā)?!
從以下三個(gè)方面來(lái)闡述下:
首先,對(duì)于架構(gòu)師來(lái)講,他應(yīng)該是精通的領(lǐng)域較廣,對(duì)技術(shù)了解比較深 刻,那么python、java、c、c++、lua、go比較了解,根據(jù)業(yè)務(wù)場(chǎng)景去選擇開 發(fā)語(yǔ)言,比如網(wǎng)易云風(fēng),在架構(gòu)網(wǎng)易游戲的時(shí)候就大量低使用了lua語(yǔ)言,因?yàn)?lua動(dòng)態(tài)解釋的,簡(jiǎn)潔小而美,方便做熱更新,方便作為實(shí)現(xiàn)業(yè)務(wù)邏輯的,是 c、c++各模塊之間的粘合劑,比如web開發(fā);java有很多成熟的庫(kù),開發(fā)效率 比較高;比如音視頻相關(guān)的開發(fā),用C和C++,因?yàn)楹芏鄨D像處理、編解碼、 音效處理大多采用了C/C++開發(fā),你再用java開發(fā)就是不倫不類的。
其次,對(duì)于軟件工程來(lái)講,注重研發(fā)效率和合理適度的架構(gòu)設(shè)計(jì),在這方 便,C和C++對(duì)于移動(dòng)互聯(lián)網(wǎng)和物聯(lián)網(wǎng)后臺(tái)服務(wù)以及基礎(chǔ)架構(gòu)設(shè)計(jì)來(lái)講,因?yàn)?能夠直接操作內(nèi)存,比如內(nèi)存溢出、棧溢出、內(nèi)存泄漏、野指針操作等會(huì)導(dǎo)致 應(yīng)用程序直接崩潰,而更加的是這些問(wèn)題可能隱藏比較深,定位BUG和解決的 成本較大,所以對(duì)開發(fā)人員的技能要求比較高,那么如果在一個(gè)團(tuán)隊(duì)內(nèi)沒(méi)有嚴(yán) 格的管理,用C和C++開發(fā)的工程代碼極難維護(hù)?,F(xiàn)在很多的后臺(tái)應(yīng)用使用java 語(yǔ)言開發(fā),但是java的框架和組件非常多,這十分容易引起過(guò)度化設(shè)計(jì)。
再者,對(duì)于企業(yè)和行業(yè)現(xiàn)狀來(lái)講,很多的企業(yè)都面臨高并發(fā)和大數(shù)據(jù)的請(qǐng) 求,對(duì)于并發(fā)或者并行開發(fā),python就免談了,壓根不合適,但是對(duì)于java語(yǔ) 言或者C/C++語(yǔ)言來(lái)講,如果采用多進(jìn)程和多線程的方式,采用這種方式時(shí), 很多時(shí)候我們采用鎖的機(jī)制解決問(wèn)題,但是采用鎖帶來(lái)的成本是很大的(可見 http://47.106.79.26:4000/2018/11/28/kernel_mutex/ 對(duì)mutex的分析), 采用多線程最著名的《并發(fā)危險(xiǎn):解決多線程代碼中的 11 個(gè)常見的問(wèn)題》( https://blog.csdn.net/mergerly/article/details/39028861)。那么在業(yè)界內(nèi) 我們采用的比較多的是lock-free的方案,比如自旋鎖和原子操作等,例如 Disruptor。幾年前我接觸了ZeroMQ的設(shè)計(jì),從ZeroMQ的主要貢獻(xiàn)者Pieter Hintjens里了解到最好的并發(fā)方式,是不共享任何資源,如果真要共享資源則 可以設(shè)計(jì)為線程通信的方式去解決。那么我們也看到go語(yǔ)言里實(shí)現(xiàn)的協(xié)程,以 及協(xié)程間用channel去通信的設(shè)計(jì)。
論述完以上三點(diǎn),那go語(yǔ)言又有哪些優(yōu)勢(shì)呢?
性能:go語(yǔ)言是一門靜態(tài)語(yǔ)言,編譯成機(jī)器字節(jié)碼,java雖然有JVM,但 是java也有JIT,可以生成字節(jié)碼去執(zhí)行。C和C++也是靜態(tài)語(yǔ)言,直接編 譯生成機(jī)器字節(jié)碼,所以go在語(yǔ)言層面的性能是接近C和C++的。關(guān)于語(yǔ) 言性能的比較我們可以從 https://benchmarksgame- team.pages.debian.net/benchmarksgame/fastest/go.html略窺一 二。但是在應(yīng)用一門語(yǔ)言時(shí),語(yǔ)言的性能僅僅是一個(gè)方面,還跟其它方面 有關(guān)系:比如跟寫代碼的人的水平和方式有關(guān)( Will your toy benchmark program be faster if you write it in a different programming language? It depends how you write it!);其二在內(nèi)存管理和IO操作上,這個(gè)就不 是語(yǔ)言層面能夠控制的了,比如C/C++能夠自己實(shí)現(xiàn)內(nèi)存的管理,比如內(nèi) 存池的技術(shù),所以對(duì)于后臺(tái)服務(wù)的應(yīng)用程序需要海量請(qǐng)求時(shí),可以從內(nèi)存
池的技術(shù)上去優(yōu)化性能,相對(duì)來(lái)說(shuō)go語(yǔ)言和其它高級(jí)語(yǔ)言沒(méi)有指針的這個(gè) 操作,所以在這方面還是不如C/C++的;其三,應(yīng)用程序的性能也符合 28原則,我們更應(yīng)當(dāng)將注意力集中在頻繁被執(zhí)行的代碼上。
go還提供了一些性能分析工具(比如pprof),通過(guò)這些工具可以分 析程序CPU使用、內(nèi)部使用,查看協(xié)程棧、GC日志和Trace信息。 語(yǔ)言技術(shù)棧:首先,go語(yǔ)言里內(nèi)置了很多的package,從其官網(wǎng)( https://golang.org/pkg/)可以查看到,基于這些package可以足夠開 發(fā)出你的應(yīng)用了,所以go語(yǔ)言是比較反對(duì)框架的;但是你也可以引入第三 方的package,如首先執(zhí)行: go
get github.com/garyburd/redigo/redis,然后import這個(gè)package, 就可以使用這個(gè)package了,現(xiàn)在很多組件都提供了go語(yǔ)言版本的接口, 也有很多第三方的框架,比如web服務(wù)的beego、buffalo、echo、gin、 iris和revel,比如微服務(wù)的非常著名并且性能彪悍的grpc,分布式文件系 統(tǒng)的go-fastdfs,對(duì)于很多的其它方面的應(yīng)用都有g(shù)o語(yǔ)言的接口實(shí)現(xiàn)。 開發(fā)效率:
編譯效率高,go語(yǔ)言的設(shè)計(jì)的初衷之一就是解決C/C++混亂的頭文 件依賴機(jī)制所導(dǎo)致的編譯時(shí)間過(guò)長(zhǎng)問(wèn)題,在GO語(yǔ)言中,有一套標(biāo)準(zhǔn) 的工程管理規(guī)范,只要按照這個(gè)規(guī)范進(jìn)行項(xiàng)目開發(fā),之后的事情 (比如包管理、編譯等等)都將變得非常的簡(jiǎn)單。在GO項(xiàng)目下,存 在兩個(gè)關(guān)鍵目錄,一個(gè)是src目錄,用于存放所有的.go源碼文件; 一個(gè)是bin目錄,用于存在編譯后的二進(jìn)制文件。在src目錄下,除 了main主包所在的目錄外,其它所有的目錄名稱與直接目錄下所對(duì) 應(yīng)的包名保持對(duì)應(yīng),否則編譯無(wú)法通過(guò)。這樣,GO編譯器就可以從 main包所在的目錄開始,完全使用目錄結(jié)構(gòu)和包名來(lái)推導(dǎo)工程結(jié)構(gòu) 以及構(gòu)建順序,避免像C++一樣,引入一個(gè)額外的Makefile文件。 在GO的編譯過(guò)程中,我們唯一要做的就是將GO項(xiàng)目路徑賦值給一 個(gè)叫GOPATH的環(huán)境變量,讓編譯器知道將要編譯的GO項(xiàng)目所在的 位置。然后進(jìn)入bin目錄下,執(zhí)行g(shù)o build {主包所在的目錄名},即 可秒級(jí)完成工程編譯。
一處編譯到處運(yùn)行, Go編譯生成的是一個(gè)靜態(tài)可執(zhí)行文件,除了 glibc 外沒(méi)有其他外部依賴。(夠浪) 學(xué)習(xí)成本:go語(yǔ)言的設(shè)計(jì)者,一開始就遵守少就是多的原則,所以 go語(yǔ)言沒(méi)有太多的特性,不像C一樣需要控制內(nèi)存,也不像 C++11/14/17/20一樣引入了特別多的語(yǔ)法特性,go的代碼比較簡(jiǎn) 單,學(xué)習(xí)的成本比較低。除此之外我們可以從官網(wǎng)和社區(qū)獲取到很 多的幫助。
Golang官網(wǎng)
Golang官方地址: golang.org,無(wú)論學(xué)習(xí)什么知識(shí),第一手資料 基本都是首發(fā)于官網(wǎng)。進(jìn)入到官網(wǎng)后,會(huì)看到很多資源,比如:
文檔:golang.org/doc,官方文檔,仔細(xì)讀下文檔首頁(yè)并分 類,了解下自己要學(xué)哪些內(nèi)容; 一覽:tour.golang.org,交互式運(yùn)行環(huán)境,不安裝golang便 可體驗(yàn)學(xué)習(xí)它的語(yǔ)法與使用; 指南:golang.org/ref/spec,golang學(xué)習(xí)指導(dǎo)手冊(cè),從基礎(chǔ) 語(yǔ)法到高級(jí)特性全部都有介紹;
標(biāo)準(zhǔn)庫(kù):golang.org/pkg/,可以查看所有的官方庫(kù)的接口、 源碼以及使用介紹; 博客:blog.golang.org,不定期分享go的最佳實(shí)踐,有些公 司也會(huì)投稿介紹自己的案例; 實(shí)驗(yàn)室:play.golang.org,感覺(jué)和tour類似,不過(guò)在這里編 寫的代碼可以分享給別人;
官網(wǎng)是個(gè)寶庫(kù),我們需要認(rèn)真仔細(xì)去挖掘其中的內(nèi)容;但由于一 些原因,golang的官方站點(diǎn)我們無(wú)法訪問(wèn),不過(guò)golang為我們提供了中國(guó)的官 網(wǎng),地址: https://go-zh.org;
golang社區(qū)
一門語(yǔ)言的發(fā)展需要有大批牛人的分享布道,也需要我們這些菜鳥學(xué)習(xí)有更多 的參考路徑。這一切都離不開社區(qū)。國(guó)內(nèi)外也有很多優(yōu)秀的go語(yǔ)言社區(qū)。
go語(yǔ)言視頻詳解:https://www.bilibili.com/video/av57709660