-
1 # 兄弟連IT教育
-
2 # 千鋒教育官方
Go語言,作為程式語言的後生,站在巨人的肩膀上,吸收了其他一些程式語言的特點。
Go 程式語言是一個開源專案,它使程式設計師更具生產力。Go 語言具有很強的表達能力,它簡潔、清晰而高效。得益於其併發機制, 用它編寫的程式能夠非常有效地利用多核與聯網的計算機,其新穎的型別系統則使程式結構變得靈活而模組化。 Go 程式碼編譯成機器碼不僅非常迅速,還具有方便的垃圾收集機制和強大的執行時反射機制。 它是一個快速的、靜態型別的編譯型語言,感覺卻像動態型別的解釋型語言。一、思想
Less can be more
大道至簡,小而蘊真
讓事情變得複雜很容易,讓事情變得簡單才難
深刻的工程文化
二、核心特性
2.1 併發程式設計
Go語言在併發程式設計方面比絕大多數語言要簡潔不少,這一點是其最大亮點之一,也是其在未來進入高併發高效能場景的重要籌碼。
不同於傳統的多程序或多執行緒,golang的併發執行單元是一種稱為goroutine的協程。由於在共享資料場景中會用到鎖,再加上GC,其併發效能有時不如非同步複用IO模型,因此相對於大多數語言來說,golang的併發程式設計簡單比並發性能更具賣點。在當今這個多核時代,併發程式設計的意義不言而喻。當然,很多語言都支援多執行緒、多程序程式設計,但遺憾的是,實現和控制起來並不是那麼令人感覺輕鬆和愉悅。Golang不同的是,語言級別支援協程(goroutine)併發(協程又稱微執行緒,比執行緒更輕量、開銷更小,效能更高),操作起來非常簡單,語言級別提供關鍵字(go)用於啟動協程,並且在同一臺機器上可以啟動成千上萬個協程。協程經常被理解為輕量級執行緒,一個執行緒可以包含多個協程,共享堆不共享棧。協程間一般由應用程式顯式實現排程,上下文切換無需下到核心層,高效不少。
協程間一般不做同步通訊,而golang中實現協程間通訊有兩種:
共享記憶體型,即使用全域性變數+mutex鎖來實現資料共享;
訊息傳遞型,即使用一種獨有的channel機制進行非同步通訊。
對比JAVA的多執行緒和GO的協程實現,明顯更直接、簡單。這就是GO的魅力所在,以簡單、高效的方式解決問題,關鍵字go,或許就是GO語言最重要的標誌。
高併發是Golang語言最大的亮點。
2.2 記憶體回收(GC)
從C到C++,從程式效能的角度來考慮,這兩種語言允許程式設計師自己管理記憶體,包括記憶體的申請和釋放等。因為沒有垃圾回收機制所以C/C++執行起來速度很快,但是隨著而來的是程式設計師對記憶體使用上的很謹小慎微的考慮。因為哪怕一點不小心就可能會導致“記憶體洩露”使得資源浪費或者“野指標”使得程式崩潰等,儘管C++11後來使用了智慧指標的概念,但是程式設計師仍然需要很小心的使用。後來為了提高程式開發的速度以及程式的健壯性,java和C#等高階語言引入了GC機制,即程式設計師不需要再考慮記憶體的回收等,而是由語言特性提供垃圾回收器來回收記憶體。但是隨之而來的可能是程式執行效率的降低。
GC過程是:先stop the world,掃描所有物件判活,把可回收物件在一段bitmap區中標記下來,接著立即start the world,恢復服務,同時起一個專門gorountine回收記憶體到空閒list中以備複用,不物理釋放。物理釋放由專門執行緒定期來執行。
GC瓶頸在於每次都要掃描所有物件來判活,待收集的物件數目越多,速度越慢。一個經驗值是掃描10w個物件需要花費1ms,所以儘量使用物件少的方案,比如我們同時考慮連結串列、map、slice、陣列來進行儲存,連結串列和map每個元素都是一個物件,而slice或陣列是一個物件,因此slice或陣列有利於GC。
GC效能可能隨著版本不斷更新會不斷最佳化,這塊沒仔細調研,團隊中有HotSpot開發者,應該會借鑑jvm gc的設計思想,比如分代回收、safepoint等。
記憶體自動回收,再也不需要開發人員管理記憶體
開發人員專注業務實現,降低了心智負擔
只需要new分配記憶體,不需要釋放
2.3 記憶體分配
初始化階段直接分配一塊大記憶體區域,大記憶體被切分成各個大小等級的塊,放入不同的空閒list中,物件分配空間時從空閒list中取出大小合適的記憶體塊。記憶體回收時,會把不用的記憶體重放回空閒list。空閒記憶體會按照一定策略合併,以減少碎片。
2.4 編譯
編譯涉及到兩個問題:編譯速度和依賴管理
目前Golang具有兩種編譯器,一種是建立在GCC基礎上的Gccgo,另外一種是分別針對64位x64和32位x86計算機的一套編譯器(6g和8g)。
依賴管理方面,由於golang絕大多數第三方開源庫都在github上,在程式碼的import中加上對應的github路徑就可以使用了,庫會預設下載到工程的pkg目錄下。另外,編譯時會預設檢查程式碼中所有實體的使用情況,凡是沒使用到的package或變數,都會編譯不透過。這是golang挺嚴謹的一面。
2.5 網路程式設計
由於golang誕生在網際網路時代,因此它天生具備了去中心化、分散式等特性,具體表現之一就是提供了豐富便捷的網路程式設計介面,比如socket用net.Dial(基於tcp/udp,封裝了傳統的connect、listen、accept等介面)、http用http.Get/Post()、rpc用client.Call("class_name.method_name", args, &reply),等等。
2.6 函式多返回值
在C,C++中,包括其他的一些高階語言是不支援多個函式返回值的。但是這項功能又確實是需要的,所以在C語言中一般透過將返回值定義成一個結構體,或者透過函式的引數引用的形式進行返回。而在Go語言中,作為一種新型的語言,目標定位為強大的語言當然不能放棄對這一需求的滿足,所以支援函式多返回值是必須的。
函式定義時可以在入參後面再加(a,b,c),表示將有3個返回值a、b、c。這個特性在很多語言都有,比如python。
這個語法糖特性是有現實意義的,比如我們經常會要求介面返回一個三元組(errno,errmsg,data),在大多數只允許一個返回值的語言中,我們只能將三元組放入一個map或陣列中返回,接收方還要寫程式碼來檢查返回值中包含了三元組,如果允許多返回值,則直接在函式定義層面上就做了強制,使程式碼更簡潔安全。
2.7 語言互動性
語言互動性指的是本語言是否能和其他語言互動,比如可以呼叫其他語言編譯的庫。
在Go語言中直接重用了大部份的C模組,這裡稱為Cgo.Cgo允許開發者混合編寫C語言程式碼,然後Cgo工具可以將這些混合的C程式碼提取並生成對於C功能的呼叫包裝程式碼。開發者基本上可以完全忽略這個Go語言和C語言的邊界是如何跨越的。
golang可以和C程式互動,但不能和C++互動。可以有兩種替代方案:1)先將c++編譯成動態庫,再由go呼叫一段c程式碼,c程式碼透過dlfcn庫動態呼叫動態庫(記得export LD_LIBRARY_PATH);2)使用swig(沒玩過)
2.8 異常處理
golang不支援try...catch這樣的結構化的異常解決方式,因為覺得會增加程式碼量,且會被濫用,不管多小的異常都丟擲。golang提倡的異常處理方式是:
普通異常:被呼叫方返回error物件,呼叫方判斷error物件。
嚴重異常:指的是中斷性panic(比如除0),使用defer...recover...panic機制來捕獲處理。嚴重異常一般由golang內部自動丟擲,不需要使用者主動丟擲,避免傳統try...catch寫得到處都是的情況。當然,使用者也可以使用panic("xxxx")主動丟擲,只是這樣就使這一套機制退化成結構化異常機制了。
2.9 其他一些有趣的特性
型別定義:支援var abc = 10這樣的語法,讓golang看上去有點像動態型別語言,但golang實際上時強型別的,前面的定義會被自動推匯出是int型別。
作為強型別語言,隱式的型別轉換是不被允許的,記住一條原則:讓所有的東西都是顯式的。
簡單來說,Go是一門寫起來像動態語言,有著動態語言開發效率的靜態語言。
一個型別只要實現了某個interface的所有方法,即可實現該interface,無需顯式去繼承。
Go程式設計規範推薦每個Interface只提供一到兩個的方法。這樣使得每個介面的目的非常清晰。另外Go的隱式推導也使得我們組織程式架構的時候更加靈活。在寫JAVA/C++程式的時候,我們一開始就需要把父類/子類/介面設計好,因為一旦後面有變更,修改起來會非常痛苦。而Go不一樣,當你在實現的過程中發現某些方法可以抽象成介面的時候,你直接定義好這個介面就OK了,其他程式碼不需要做任何修改,編譯器的自動推導會幫你做好一切。
不能迴圈引用:
即如果a.go中import了b,則b.go要是import a會報import cycle not allowed。好處是可以避免一些潛在的程式設計危險,比如a中的func1()呼叫了b中的func2(),如果func2()也能呼叫func1(),將會導致無限迴圈呼叫下去。
defer機制:
在Go語言中,提供關鍵字defer,可以透過該關鍵字指定需要延遲執行的邏輯體,即在函式體return前或出現panic時執行。這種機制非常適合善後邏輯處理,比如可以儘早避免可能出現的資源洩漏問題。
【劃重點】可以說,defer是繼goroutine和channel之後的另一個非常重要、實用的語言特性,對defer的引入,在很大程度上可以簡化程式設計,並且在語言描述上顯得更為自然,極大的增強了程式碼的可讀性。
“包”的概念:
和python一樣,把相同功能的程式碼放到一個目錄,稱之為包。包可以被其他包引用。main包是用來生成可執行檔案,每個程式只有一個main包。包的主要用途是提高程式碼的可複用性。透過package可以引入其他包。
程式設計規範:
GO語言的程式設計規範強制整合在語言中,比如明確規定花括號擺放位置,強制要求一行一句,不允許匯入沒有使用的包,不允許定義沒有使用的變數,提供gofmt工具強制格式化程式碼等等。奇怪的是,這些也引起了很多程式設計師的不滿,有人發表GO語言的XX條罪狀,裡面就不乏對程式設計規範的指責。要知道,從工程管理的角度,任何一個開發團隊都會對特定語言制定特定的程式設計規範,特別像Google這樣的公司,更是如此。GO的設計者們認為,與其將規範寫在文件裡,還不如強制整合在語言裡,這樣更直接,更有利用團隊協作和工程管理。
交叉編譯:
比如說你可以在執行 Linux 系統的計算機上開發執行 Windows 下執行的應用程式。這是第一門完全支援 UTF-8 的程式語言,這不僅體現在它可以處理使用 UTF-8 編碼的字串,就連它的原始碼檔案格式都是使用的 UTF-8 編碼。Go 語言做到了真正的國際化!
三、功能
此處我們說個小段子:
規範的語法(不需要符號表來解析)
垃圾回收(獨有)
無標頭檔案
明確的依賴
無迴圈依賴
常量只能是數字
int和int32是兩種型別
字母大小寫設定可見性(letter case sets visibility)
任何型別(type)都有方法(不是型別)
沒有子型別繼承(不是子類)
包級別初始化以及明確的初始化順序
檔案被編譯到一個包裡
包package-level globals presented in any order
沒有數值型別轉換(常量起輔助作用)
介面隱式實現(沒有“implement”宣告)
嵌入(不會提升到超類)
方法按照函式宣告(沒有特別的位置要求)
方法即函式
介面只有方法(沒有資料)
方法透過名字匹配(而非型別)
沒有建構函式和解構函式
postincrement(如++i)是狀態,不是表示式
沒有preincrement(i++)和predecrement
賦值不是表示式
明確賦值和函式呼叫中的計算順序(沒有“sequence point”)
沒有指標運算
記憶體一直以零值初始化
區域性變數取值合法
方法中沒有“this”
分段的堆疊
沒有靜態和其它型別的註釋
沒有模板
內建string、slice和map
陣列邊界檢查
最後介紹下大牛真身,最大牌的當屬B和C語言設計者、Unix和Plan 9創始人、1983年圖靈獎獲得者Ken Thompson,這份名單中還包括了Unix核心成員Rob Pike(go語言之父)、java HotSpot虛擬機器和js v8引擎的開發者Robert Griesemer、Memcached作者Brad Fitzpatrick,等等。
四、Go 語言能做什麼
Go 語言從釋出 1.0 版本以來備受眾多開發者關注並得到廣泛使用,Go 語言的簡單、高效、併發特性吸引了眾多傳統語言開發者的加入,而且人數越來越多。
鑑於Go語言的特點和設計的初衷,Go語言作為伺服器程式語言,很適合處理日誌、資料打包、虛擬機器處理、檔案系統、分散式系統、資料庫代理等;網路程式設計方面,Go語言廣泛應用於Web 應用、API應用、下載應用等;除此之外,Go語言還適用於記憶體資料庫和雲平臺領域,目前國外很多雲平臺都是採用Go開發。
伺服器程式設計,以前你如果使用C或者C++做的那些事情,用Go來做很合適,例如處理日誌、資料打包、虛擬機器處理、檔案系統等。
分散式系統、資料庫代理器、中介軟體等,例如Etcd。
網路程式設計,這一塊目前應用最廣,包括Web應用、API應用、下載應用,而且Go內建的net/http包基本上把我們平常用到的網路功能都實現了。
資料庫操作
開發雲平臺,目前國外很多雲平臺在採用Go開發。
五、國內外有哪些企業或專案使用Go語言
Go釋出之後,很多公司特別是雲計算公司開始用Go重構他們的基礎架構,很多都是直接採用Go進行了開發,最近熱火朝天的Docker就是採用Go開發的。
使用 Go 語言開發的開源專案非常多。早期的 Go 語言開源專案只是透過 Go 語言與傳統專案進行C語言庫繫結實現,例如 Qt、Sqlite 等;後期的很多專案都使用 Go 語言進行重新原生實現,這個過程相對於其他語言要簡單一些,這也促成了大量使用 Go 語言原生開發專案的出現。
雲計算基礎設施領域,代表專案有:docker、kubernetes、etcd、consul、cloudflare CDN、七牛雲端儲存等
基礎軟體領域代表專案有:tidb、influxdb、cockroachdb等。
微服務領域代表專案有:go-kit、micro、monzo bank的typhon、bilibili等。
網際網路基礎設施領域有:以太坊、hyperledger等。
採用Go的一些國外公司,如Google、Docker、Apple、Cloud Foundry、CloudFlare、Couchbase、CoreOS、Dropbox、MongoDB、AWS等公司;
採用Go開發的國內企業:如阿里雲、百度、小米、七牛、PingCAP、華為、金山軟體、獵豹移動、餓了麼等公司。
下面著重介紹幾個:
Docker
簡介:Docker 是一種作業系統層面的虛擬化技術,可以在作業系統和應用程式之間進行隔離,也可以稱之為容器。Docker 可以在一臺物理伺服器上快速執行一個或多個例項。基於lxc的一個虛擬打包工具,能夠實現PAAS平臺的組建。例如,啟動一個 CentOS 作業系統,並在其內部命令列執行指令後結束,整個過程就像自己在作業系統一樣高效。專案連結:https://github.com/docker/dockerKubernetes
簡介:Google 公司開發的構建於 Docker 之上的容器排程服務,使用者可以透過 Kubernetes 叢集進行雲端容器叢集管理。
專案連結:https://github.com/kubernetes/kubernetes
etcd
專案連結:https://github.com/coreos/etcd
簡介:一款分散式、可靠的 KV 儲存系統,可以快速進行雲配置。
回覆列表
什麼是Go?
Go語言是谷歌2009釋出的第二款開源程式語言。
Go語言專門針對多處理器系統應用程式的程式設計進行了最佳化,使用Go編譯的程式可以媲美C或C++程式碼的速度,而且更加安全、支援並行程序。不僅可以開發web,可以開發底層,目前知乎就是用golang開發。區塊鏈首選語言就是go,以太坊,超級賬本都是基於go語言,還有go語言版本的btcd.
Go的目標是希望提升現有程式語言對程式庫等依賴性(dependency)的管理,這些軟體元素會被應用程式反覆呼叫。由於存在並行程式設計模式,因此這一語言也被設計用來解決多處理器的任務。
Google對Go寄予厚望。其設計是讓軟體充分發揮多核心處理器同步多工的優點,並可解決面向物件程式設計的麻煩。它具有現代的程式語言特色,如垃圾回收,幫助程式設計師處理瑣碎但重要的記憶體管理問題。Go的速度也非常快,幾乎和C或C++程式一樣快,且能夠快速製作程式。
Go的網站就是用Go所建立,但Google有更大的野心。該軟體是專為構建伺服器軟體所設計(如Google的Gmail)。Google認為Go還可應用到其他領域,包括在瀏覽器內執行軟體,取代JavaScript的角色。
為什麼要學習GO語言,GO的優勢是什麼?
1、 Go有什麼優勢
Go的優勢
1:效能
2:語言效能很重要
3:開發者效率&不要過於創新
4:併發性&通道
5:快速的編譯時間
6:打造團隊的能力
7:強大的生態系統
8:GOFMT,強制程式碼格式
9:gRPC 和 Protocol Buffers
可直接編譯成機器碼,不依賴其他庫,glibc的版本有一定要求,部署就是扔一個檔案上去就完成了。
靜態型別語言,但是有動態語言的感覺,靜態型別的語言就是可以在編譯的時候檢查出來隱藏的大多數問題,動態語言的感覺就是有很多的包可以使用,寫起來的效率很高。
語言層面支援併發,這個就是Go最大的特色,天生的支援併發,我曾經說過一句話,天生的基因和整容是有區別的,大家一樣美麗,但是你喜歡整容的還是天生基因的美麗呢?Go就是基因裡面支援的併發,可以充分的利用多核,很容易的使用併發。
內建runtime,支援垃圾回收,這屬於動態語言的特性之一吧,雖然目前來說GC不算完美,但是足以應付我們所能遇到的大多數情況,特別是Go1.1之後的GC。
簡單易學,Go語言的作者都有C的基因,那麼Go自然而然就有了C的基因,那麼Go關鍵字是25個,但是表達能力很強大,幾乎支援大多數你在其他語言見過的特性:繼承、過載、物件等。
豐富的標準庫,Go目前已經內建了大量的庫,特別是網路庫非常強大,我最愛的也是這部分。
內建強大的工具,Go語言裡面內建了很多工具鏈,最好的應該是gofmt工具,自動化格式化程式碼,能夠讓團隊review變得如此的簡單,程式碼格式一模一樣,想不一樣都很困難。
跨平臺編譯,如果你寫的Go程式碼不包含cgo,那麼就可以做到window系統編譯linux的應用,如何做到的呢?Go引用了plan9的程式碼,這就是不依賴系統的資訊。
內嵌C支援,前面說了作者是C的作者,所以Go裡面也可以直接包含c程式碼,利用現有的豐富的C庫。
2、Go適合用來做什麼
伺服器程式設計,以前你如果使用C或者C++做的那些事情,用Go來做很合適,例如處理日誌、資料打包、虛擬機器處理、檔案系統等。
分散式系統,資料庫代理器等
網路程式設計,這一塊目前應用最廣,包括Web應用、API應用、下載應用、
記憶體資料庫,前一段時間google開發的groupcache,couchbase的部分組建
雲平臺,目前國外很多雲平臺在採用Go開發,CloudFoundy的部分組建,前VMare的技術總監自己出來搞的apcera雲平臺。
3、Go成功的專案nsq:bitly開源的訊息佇列系統,效能非常高,目前他們每天處理數十億條的訊息docker:基於lxc的一個虛擬打包工具,能夠實現PAAS平臺的組建。packer:用來生成不同平臺的映象檔案,例如VM、vbox、AWS等,作者是vagrant的作者skynet:分散式排程框架Doozer:分散式同步工具,類似ZooKeeperHeka:mazila開源的日誌處理系統cbfs:couchbase開源的分散式檔案系統tsuru:開源的PAAS平臺,和SAE實現的功能一模一樣groupcache:memcahe作者寫的用於Google下載系統的快取系統god:類似redis的快取系統,但是支援分散式和擴充套件性gor:網路流量抓包和重放工具以下是一些公司,只是一小部分:
下面列出來了一些使用的使用者GoUsers - go-wiki - A list of organizations that use Go.4、Go還存在的缺點以下缺點是我自己在專案開發中遇到的一些問題:
Go的import包不支援版本,有時候升級容易導致專案不可執行,所以需要自己控制相應的版本資訊
Go的goroutine一旦啟動之後,不同的goroutine之間切換不是受程式控制,runtime排程的時候,需要嚴謹的邏輯,不然goroutine休眠,過一段時間邏輯結束了,突然冒出來又執行了,會導致邏輯出錯等情況。
GC延遲有點大,我開發的日誌系統傷過一次,同時併發很大的情況下,處理很大的日誌,GC沒有那麼快,記憶體回收不給力,後來經過profile程式改進之後得到了改善。
pkg下面的圖片處理庫很多bug,還是使用成熟產品好,呼叫這些成熟庫imagemagick的介面比較靠譜
最後還是建議大家學習Go,這門語言真的值得大家好好學習,因為它可以做從底層到前端的任何工作。