Overview
本文討論了服務(wù)器領(lǐng)域常見的并發(fā)等問題影锈,也涉及到了工程化相關(guān)的問題延曙,也整理了C背景程序員對(duì)于Go的GC以及性能的疑問豌鹤,探討了Go的錯(cuò)誤處理和類型系統(tǒng)最佳實(shí)踐,以及依賴管理的難處枝缔,接口設(shè)計(jì)的正交性布疙,當(dāng)然也包含我們在服務(wù)器開發(fā)中對(duì)于Go實(shí)踐的總結(jié),有時(shí)候也對(duì)一些有趣的問題做深度的挖掘愿卸,也列出了Go重要的事件和資料集合灵临,還有Go2的進(jìn)展和思考。我更想從問題本身出發(fā)擦酌,不局限于Go語言俱诸,探討服務(wù)器中常常遇到的問題菠劝,最后回到Go如何解決這些問題赊舶,提供Go開發(fā)的關(guān)鍵技術(shù)指南。
About the Name
The Go Programming Language到底是該叫GO還是GOLANG赶诊?Google搜Why Go is called Golang
能搜到幾篇經(jīng)典帖子笼平。
Rob Pike在Twitter上特意說明是Go,可以看這個(gè)The language is called Go:
Neither. The language is called Go, not Golang. http://golang.org is just the the web site address, not the name of the language.
那么在另外一個(gè)地方也說明了也是Go舔痪,可以看這個(gè)The name of our language is go:
The name of our language is Go
Ruby is called Ruby, not Rubylang.
Python is called Python, not Pythonlang.
C is called C, not Clang. No. Wait. That was a bad example.
Go is called Go, not Golang.
Yes, yes, I know all about the searching and meta tags. Sure, whatever,
but that doesn't change the fact that the name of the language is Go.
Thank you for your consideration.
這里舉了各種例子說明為何不加lang的后綴寓调,當(dāng)然有個(gè)典型的語言是加的,就是Erlang
锄码。于是就有回復(fù)說“Erlang Erlang, Let's just call it Er.”
那么為何很多時(shí)候Go和Golang都很常用呢夺英?在Why is the Go programming language usually called Golang中說的比較清楚:
It’s because “go domain” has been registered by Walt Disney and so Go creators couldn’t use it.
So, they have decided to use golang for the domain name. Then the rest came.
Also, it’s harder to search things on search engines just using the word Go. Although, Rob Pike is
against this idea but I disagree. Most of the time, for the correct results you need to search for
golang.
It’s just Go, not golang but it sticked to it.
講個(gè)笑話先,用百度搜下為何Go叫做Golang滋捶,一大片都是類似本文的雞湯煲痛悯,告訴你為何Go才是天地間最合適你的語言,當(dāng)然本文要成為雞湯煲中的戰(zhàn)斗煲重窟,告訴你全家都應(yīng)該選擇Go語言载萌。
為何Go語言名字是Go,但是經(jīng)常說成是Golang呢?有以下理由:
- go.org被注冊了扭仁,正在賣垮衷,也不貴才1698萬。所以Go只能用golang.org乖坠。
- 搜點(diǎn)啥信息如果搜go搀突,太寬泛了,特別是go還沒有這么多用戶時(shí)熊泵,搜golang能更精確的找到答案描姚。
為什么在名字上要這么糾結(jié)呢?嗯嗯戈次,不糾結(jié)轩勘,讓我們開始干雞湯吧。
Why Go?
考慮一個(gè)商用的快速發(fā)展的業(yè)務(wù)后端服務(wù)器怯邪,最重要的是什么绊寻?當(dāng)然是穩(wěn)定性了,如果崩潰可能會(huì)造成用戶服務(wù)中斷悬秉,崩潰的問題在C/C++服務(wù)器中幾乎是必然的:
- 穩(wěn)定是一種假象澄步。想象一個(gè)C服務(wù)器,一般不會(huì)重頭碼所有的代碼和泌,會(huì)從一個(gè)開源版本開始村缸,或者從一些網(wǎng)絡(luò)和線程庫開始,然后不斷改進(jìn)和完善武氓,由于業(yè)務(wù)前期并不復(fù)雜梯皿,上線也沒有發(fā)現(xiàn)問題,這時(shí)候可以說C服務(wù)器是穩(wěn)定的嗎县恕?當(dāng)然不是东羹,只是Bug沒有觸發(fā)而已,所有崩潰的Bug都幾乎不是本次發(fā)布導(dǎo)致的問題忠烛。野指針和越界是C服務(wù)器中最難搞定的狼人属提,這些狼人還喜歡玩潛伏。
- 穩(wěn)定是短暫美尸,不穩(wěn)定是必然和長期冤议。一般業(yè)務(wù)會(huì)突飛猛進(jìn),特別是越偏上層的業(yè)務(wù)师坎,需要后端處理的邏輯就越多恕酸,至于UTest和測試一般只存在于傳說中,隨著業(yè)務(wù)的發(fā)展屹耐,潛伏的狼人越來越多尸疆,甚至開源的庫和服務(wù)器中的狼人也開始出來作妖椿猎。夜路走多了,總會(huì)碰到鬼寿弱。碰到鬼了怎么辦犯眠,遇鬼殺鬼了,還能被它嚇尿不成症革,所以就反思解決Bug筐咧,費(fèi)了老勁了,又白了幾根頭發(fā)噪矛,終于迎來短暫安寧量蕊,然后繼續(xù)寫B(tài)ug。
- 最普遍的問題還是內(nèi)存問題導(dǎo)致崩潰艇挨,一般就是野指針和越界残炮。空指針問題相對(duì)很容易查缩滨,除零之類的典型錯(cuò)誤也容易處理势就。最完善的解決辦法,就是實(shí)現(xiàn)GC脉漏,讓指針總是有效苞冯,無效后再釋放,越界時(shí)能檢測到這樣容易解決問題侧巨;嗯舅锄,其實(shí)Go早期的版本就和這個(gè)很類似了,要實(shí)現(xiàn)帶GC的C的同學(xué)司忱,可以參考下Go的實(shí)現(xiàn)皇忿。
- 線上的CPU和內(nèi)存的問題,一般不方便使用工具查看烘贴,而線上的問題有時(shí)候很難在本地重現(xiàn)禁添。如何能直接獲取線上的Profile數(shù)據(jù),需要程序本身支持桨踪。比如提供HTTP API能獲取到Profile數(shù)據(jù)?關(guān)鍵是如何采集這些數(shù)據(jù)芹啥。
Go的使命愿景和價(jià)值觀:
Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.
Go is a concurrent open source programming language developed at Google. Combines native compilation and static types with a lightweight dynamic feel. Fast, fun, and productive.
Go is an attempt to make programmers more productive. The first goal is to make a better language to meet the challenges of scalable concurrency. The larger goal is to make a better environment to meet the challenges of scalable software development, software worked on and used by many people, with limited coordination between them, and maintained for years.
Go語言的關(guān)鍵字:
- 運(yùn)行性能高: Statically typed. Native code generation (compiled). Efficiency. Fast development cycle.
- 碼農(nóng)不苦逼: Memory safe. Garbage collected. Safety.
- 云計(jì)算專享: Native concurrency support. Concurrency. Scalability.
- 工程師思維: Composition via interfaces. Excellent standard library. Great tools.
參考The Path to Go1: What is Go?和Another Go at Language Design锻离。
Go是面向軟件工程的語言墓怀,Go在工程上的思考可以讀Go at Google: Language Design in the Service of Software Engineering和Less is exponentially more汽纠。Go最初是解決Google遇到的大規(guī)模系統(tǒng)和計(jì)算的問題,這些問題如今被稱為云計(jì)算傀履,參考Go, Open Source, Community虱朵。
GITHUT上顯示Go的項(xiàng)目和PR一直在上升,如下圖所示。
2014云計(jì)算行業(yè)中使用Go的有:Docker, Kubernetes, Packer, Serf, InfluxDB, Cloud Foundry’s gorouter and CLI, CoreOS’s etcd and fleet, Vitess, YouTube’s tooling for MySQL scaling, Canonical’s Juju (rewritten in Go), Mozilla’s Heka, A Go interface to OpenStack Swift, Heroku’s Force.com and hk CLIs, Apcera’s NATS and gnatsd碴犬。
2018年全球使用Go的公司數(shù)目有:US(329), Japan(79), Brazil(52), India(49), Indonesia(45), China(32), UK(32), Germany(28), Israel(24), France(17), Netherlands(16), Canada (15), Thailand(14), Turkey(14), Spain(12), Poland(11), Australia(9), Russia(9), Iran(8), Sweden(7), Korea(South)(6), Switzerland(6), Ukraine(5)絮宁。
參考Go as the emerging language of cloud infrastructure,以及The RedMonk Programming Language Rankings: June 2018服协,還有GoUsers绍昂,以及Success Stories。
參考Nine years of Go: Go Contributors窘游,社區(qū)貢獻(xiàn)的代碼比例。
我們一起看看這些Go牛逼的特性跳纳,詳細(xì)分析每個(gè)點(diǎn)忍饰,雖然不能涵蓋所有的點(diǎn),對(duì)于常用的Go的特性我們做一次探討和分析寺庄。
Milestones
看看Go做到了哪些喘批,Go的重要事件:
- 2019.09, Go1.13發(fā)布。增強(qiáng)了modules铣揉,新增了環(huán)境變量GOPRIVATE和GOSUMDB饶深,GOPROXY支持多個(gè)。支持了ErrorWraping逛拱。
- 2019.02, Go1.12發(fā)布敌厘,支持了TLS1.3,改進(jìn)了modules朽合,優(yōu)化運(yùn)行時(shí)和標(biāo)準(zhǔn)庫俱两。
- 2018.08, Go1.11發(fā)布,實(shí)驗(yàn)性支持modules曹步,實(shí)驗(yàn)性支持WebAssembly
- 2018.02, Go1.10發(fā)布宪彩,go tool緩存編譯,編譯加速讲婚,很多細(xì)微的改進(jìn)尿孔。
- 2018.01, Hello, 中國!, 中國站鏡像上線,大陸可以訪問官網(wǎng)資源筹麸。
- 2017.08, Go1.9發(fā)布活合,支持Type Alias,支持sync.Map物赶,使用場景參考slides白指,time保持單增避免時(shí)間測量問題。
- 2017.02, Go1.8發(fā)布酵紫,顯著的性能提升告嘲,GC延遲降低到了10us到100us错维,支持HTTP/2 Push,HTTP Server支持Shutdown橄唬,
sort.Slice
使排序使用更簡單赋焕。 - 2016.08, Go1.7發(fā)布,支持了Context轧坎,Context在K8S和Docker中都有應(yīng)用宏邮,新的編譯算法減少20-30%的二進(jìn)制尺寸。
- 2016.02, Go1.6發(fā)布缸血,支持HTTP/2蜜氨,HTTPS時(shí)會(huì)默認(rèn)開啟HTTP/2,正式支持vendor捎泻。
- 2015.08, Go1.5發(fā)布恩溅,完全用Go代替了C代碼廉油,完全重新設(shè)計(jì)和重新實(shí)現(xiàn)GC,支持internal的package,實(shí)驗(yàn)性支持vendor饵婆,GOMAXPROCS默認(rèn)為CPU個(gè)數(shù)铣耘。
- 2014.12, Go1.4發(fā)布票堵,支持Android慎璧,從Mecurial遷移到了Git,從GoogleCode遷移到了Github: golang/go哄孤,大部分runtime的代碼從C改成了Go照筑,
for
支持三種迭代寫法。 - 2014.06, Go1.3發(fā)布瘦陈,支持了FreeBSD凝危,Plan9,Solaris等系統(tǒng)晨逝。
- 2013.12, Go1.2發(fā)布蛾默,新增收集覆蓋率工具coverage,限制了最高線程數(shù)ThreadLimit捉貌。
- 2013.05, Go1.1發(fā)布支鸡,主要是包含性能優(yōu)化,新增
Data Race Detector
等昏翰。 - 2012.03, Go1.0發(fā)布苍匆,包含了基本的語言元素比如rune、error棚菊、map,標(biāo)準(zhǔn)庫包括bufio叔汁、crypto统求、flag检碗、http、net码邻、os折剃、regexp、runtime像屋、unsafe怕犁、url、encoding等己莺。
- 2009.11, Google宣布要開發(fā)一門新語言奏甫,既要開源,又有Python的好處凌受,還要有C/C++的性能阵子。GO是BSD的License,大部分GO的項(xiàng)目都是BSD或MIT或Apache等商業(yè)友好的協(xié)議胜蛉。
Links
由于簡書限制了文章字?jǐn)?shù)挠进,只好分成不同章節(jié):
- Overview 為何Go有時(shí)候也叫Golang?為何要選擇Go作為服務(wù)器開發(fā)的語言?是沖動(dòng)誊册?還是騷動(dòng)领突?Go的重要里程碑和事件,當(dāng)年吹的那些牛逼案怯,都實(shí)現(xiàn)了哪些君旦?
- Could Not Recover 君可知,有什么panic是無法recover的殴泰?包括超過系統(tǒng)線程限制于宙,以及map的競爭寫。當(dāng)然一般都能recover悍汛,比如Slice越界捞魁、nil指針、除零离咐、寫關(guān)閉的chan等谱俭。
- Errors 為什么Go2的草稿3個(gè)有2個(gè)是關(guān)于錯(cuò)誤處理的?好的錯(cuò)誤處理應(yīng)該怎么做宵蛀?錯(cuò)誤和異常機(jī)制的差別是什么昆著?錯(cuò)誤處理和日志如何配合?
- Logger 為什么標(biāo)準(zhǔn)庫的Logger是完全不夠用的术陶?怎么做日志切割和輪轉(zhuǎn)凑懂?怎么在混成一坨的服務(wù)器日志中找到某個(gè)連接的日志?甚至連接中的流的日志梧宫?怎么做到簡潔又夠用接谨?
- Interfaces 什么是面向?qū)ο蟮腟OLID原則摆碉?為何Go更符合SOLID?為何接口組合比繼承多態(tài)更具有正交性脓豪?Go類型系統(tǒng)如何做到looser, organic, decoupled, independent, and therefore scalable巷帝?一般軟件中如果出現(xiàn)數(shù)學(xué),要么真的牛逼要么裝逼扫夜。正交性這個(gè)數(shù)學(xué)概念在Go中頻繁出現(xiàn)楞泼,是神仙還是妖怪?為何接口設(shè)計(jì)要考慮正交性笤闯?
- Modules 如何避免依賴地獄(Dependency Hell)堕阔?小小的版本號(hào)為何會(huì)帶來大災(zāi)難?Go為什么推出了GOPATH望侈、Vendor還要搞module和vgo印蔬?新建了16個(gè)倉庫做測試,碰到了9個(gè)坑脱衙,搞清楚了gopath和vendor如何遷移侥猬,以及vgo with vendor如何使用(畢竟生產(chǎn)環(huán)境不能每次都去外網(wǎng)下載)。
- Concurrency & Control 服務(wù)器中的并發(fā)處理難在哪里捐韩?為什么說Go并發(fā)處理優(yōu)勢占領(lǐng)了云計(jì)算開發(fā)語言市場退唠?什么是C10K、C10M問題荤胁?如何管理goroutine的取消瞧预、超時(shí)和關(guān)聯(lián)取消?為何Go1.7專門將context放到了標(biāo)準(zhǔn)庫仅政?context如何使用垢油,以及問題在哪里?
- Engineering Go在工程化上的優(yōu)勢是什么圆丹?為什么說Go是一門面向工程的語言滩愁?覆蓋率要到多少比較合適?什么叫代碼可測性辫封?為什么良好的庫必須先寫Example硝枉?
- Go2 Transition Go2會(huì)像Python3不兼容Python2那樣作嗎?C和C++的語言演進(jìn)可以有什么不同的收獲倦微?Go2怎么思考語言升級(jí)的問題妻味?
- SRS & Others Go在流媒體服務(wù)器中的使用。Go的GC靠譜嗎欣福?Twitter說相當(dāng)?shù)目孔V责球,有圖有真相。為何Go的聲明語法是那樣?C的又是怎樣棕诵?是拍的大腿裁良,還是拍的腦袋凿将?