golang快速入門[1]-go語言導論

聲明

  • 這是一套幫助初學者從0到1學習go語言的開源教程,致力于打造最完整、最強悍、最有深度的Go語言學習體系
  • 我希望這套課程能夠涵蓋Go語言的所有體系、并致力于用大量的案例來詮釋其用法
  • 鑒于作者水平有限,真誠地希望能夠集所有人的智慧,完善此項目,鏈接附后

簡介

  • Go(又稱Golang)是Google開發的一種靜態強類型、編譯型、并發型,并具有垃圾回收功能的編程語言
  • Go的最初目標是消除Google軟件開發的緩慢性和笨拙性,從而使流程更具效率和可擴展性,更多的關注于軟件工程領域
  • Go致力于解決當代大型工程項目面臨的多核處理,網絡系統,海量計算集群、快速構建等問題,Go在語言級別考慮并發問題,提供簡單高效的并發編程
  • 羅伯特·格瑞史莫(Robert Griesemer),羅勃·派克(Rob Pike)及肯·湯普遜(Ken Thompson)于2007年9月開始設計Go,稍后Ian Lance Taylor、Russ Cox加入項目
  • Go是基于Inferno操作系統所開發的
  • Go于2009年11月正式宣布推出,成為開放源代碼項目,支持Linux、macOS、Windows等操作系統
  • 在2016年,Go被軟件評價公司TIOBE 選為“TIOBE 2016 年最佳語言”
  • 很多重要的開源項目都是使用Go語言開發的,其中包括 Docker、Go-Ethereum、Thrraform、Kubernetes、etcd、hyperledger、tidb

基本語言的歷史

  • 1960年 Ken Thompson(肯.湯普森) 發明了B語言
  • 1972年 Dennis Ritchie(丹尼斯·里奇)發明了C語言
  • 1982年 Bjarne Stroustrup(本賈尼)發明了C++語言
  • 1989年 Guido von Rossum 發明了Python語言
  • 1995年SUN公司發明了Java語言
  • 2007年Go語言誕生
  • 2009年的11月對外正式發布

Go語言創始人

對語言進行評估時,明白設計者的動機以及語言要解決的問題很重要。Go語言出自 Ken Thompson 和 Rob Pike、Robert Griesemer 之手,他們都是計算機科學領域的重量級人物。

  • Ken Thompson
    貝爾實驗室 Unix 團隊成員,C語言、Unix 和 Plan 9 的創始人之一,在 20 世紀 70 年代,設計并實現了最初的 UNIX 操作系統,僅從這一點說,他對計算機科學的貢獻怎么強調都不過分。他還與 Rob Pike 合作設計了 UTF-8 編碼方案
  • Rob Pike
    Go語言項目總負責人,貝爾實驗室 Unix 團隊成員,除幫助設計 UTF-8 外,還幫助開發了分布式多用戶操作系統 Plan 9、Inferno 操作系統和 Limbo 編程語言,并與人合著了《The Unix Programming Environment》,對 UNIX 的設計理念做了正統的闡述
  • Robert Griesemer
    就職于 Google,參與開發 Java HotSpot 虛擬機,對語言設計有深入的認識,并負責 Chrome 瀏覽器和 Node.js 使用的 Google V8 JavaScript 引擎的代碼生成部分

go語言的繼承

  • Go語言有時候被描述為“C類似語言”,或者是“21世紀的C語言”

  • Go從C語言繼承了相似的表達式語法、控制流結構、基礎數據類型、調用參數傳值、指針等思想

  • Go繼承了C語言一直所看中的編譯后機器碼的運行效率以及和現有操作系統的無縫適配

  • Go語言的家族樹中還有其它的祖先。其中一個有影響力的分支來自Niklaus Wirth所設計的Pascal語言

  • Modula-2語言激發了包的概念,然后Oberon語言摒棄了模塊接口文件和模塊實現文件之間的區別。第二代的Oberon-2語言直接影響了包的導入和聲明的語法,還有Oberon語言的面向對象特性所提供的方法的聲明語法等

  • Go語言的另一支祖先,帶來了Go語言區別其他語言的重要特性,靈感來自于貝爾實驗室的Tony Hoare于1978年發表的鮮為外界所知的關于并發研究的基礎文獻順序通信進程(communicating sequential processes,縮寫為CSP)

  • 在CSP中,程序是一組中間沒有共享狀態的平行運行的處理過程,它們之間使用管道進行通信和控制同步。不過Tony Hoare的CSP只是一個用于描述并發性基本概念的描述語言,并不是一個可以編寫可執行程序的通用編程語言

  • Rob Pike和其他人開始不斷嘗試將CSP引入實際的編程語言中。他們第一次嘗試引入CSP特性的編程語言叫Squeak,是一個提供鼠標和鍵盤事件處理的編程語言,它的管道是靜態創建的

  • 然后是改進版的Newsqueak語言,提供了類似C語言語句和表達式的語法和類似Pascal語言的推導語法。Newsqueak是一個帶垃圾回收的純函數式語言,它再次針對鍵盤、鼠標和窗口事件管理。在Newsqueak語言中管道是動態創建的,屬于第一等公民,可以保存到變量中

  • 在Plan9操作系統中,這些優秀的想法被吸收到了一個叫Alef的編程語言中。Alef試圖將Newsqueak語言改造為系統編程語言,但是因為缺少垃圾回收機制而導致并發編程很痛苦

  • 注:在Aelf之后還有一個叫Limbo的編程語言,Go語言從其中借鑒了很多特性。具體請參考Pike的講稿:http://talks.golang.org/2012/concurrency.slide#9

  • Go語言的其他的一些特性零散地來自于其他一些編程語言;比如iota語法是從APL語言借鑒,詞法作用域與嵌套函數來自于Scheme語言和其他很多語言

  • Go中也有很多創新的設計,比如Go語言的切片為動態數組提供了有效的隨機存取的性能,還有Go語言新發明的defer語句

go語言的特點

所有的編程語言都反映了語言設計者對編程哲學的反思,通常包括之前的語言所暴露的一些不足地方的改進。

  • 簡潔

  • Go項目是在Google公司維護超級復雜的幾個軟件系統遇到的一些問題的反思(但是這類問題絕不是Google公司所特有的)

  • 正如Rob Pike所說,“軟件的復雜性是乘法級相關的”,通過增加一個部分的復雜性來修復問題通常將慢慢地增加其他部分的復雜性

  • 通過增加功能、選項、配置是修復問題的最快的途徑,但是這很容易讓人忘記簡潔的內涵,卽使從長遠來看,簡潔依然是好軟件的關鍵因素

  • 簡潔的設計需要在工作開始的時候舍棄不必要的想法,并且在軟件的生命周期內嚴格區別好的改變或壞的改變。通過足夠的努力,一個好的改變可以在不破壞原有完整概念的前提下保持自適應

  • 而一個壞的改變則不能達到這個效果,它們僅僅是通過膚淺的和簡單的妥協來破壞原有設計的一致性。只有通過簡潔的設計,才能讓一個系統保持穩定、安全和持續的進化

  • 附帶了相關的工具和標準庫

  • 沒有隱式的數值轉換

  • 沒有構造函數和析構函數

  • 沒有運算符重載

  • 沒有默認參數

  • 沒有繼承

  • 沒有泛型(go2中考慮加入)

  • 沒有異常,即沒有與錯誤處理相關的控制結構

  • 沒有宏

  • 沒有函數修飾

  • 沒有線程局部存儲。

  • 沒有指針運算

  • 沒有類型別名

  • 數組邊界總是受到檢查

  • 基本特性

  • 自動垃圾回收

  • 包管理

  • 函數作為一等公民

  • 系統調用接口

  • 只讀的UTF8字符串

  • 函數多返回值

  • 匿名函數和閉包

  • 反射

  • 靜態鏈接

  • 嚴格的依賴規范

  • CSP并發編程

  • Goroutine協程

  • 接口類型

  • 向后兼容

  • Go語言本身是成熟和穩定的,而且承諾保證向后兼容:用之前的Go語言編寫程序可以用新版本的Go語言編譯器和標準庫直接構建而不需要修改代碼

  • 類型系統

  • 相比較于js、python,Go語言的類型系統避免動態語言中那些粗心的類型錯誤。但是Go語言的類型系統相比傳統的強類型語言又要簡潔很多,雖然有時候這會導致一個“無類型”的抽象類型的概念

  • Go語言程序員并不需要像C++或Haskell程序員那樣糾結于具體類型的安全屬性。在實踐中Go語言簡潔的類型系統給了程序員帶來了更多的安全性和更好的運行時性能

  • Go語言遵循當代計算機系統設計的原則,特別是局部的重要性。Go的內置數據類型和大多數的標準數據結構都經過精心設計而避免顯式的初始化或隱式的構造函數,因此內存分配和內存初始化代碼被隱藏在庫代碼中了

  • Go語言的聚合類型(結構體和數組)可以直接操作它們的元素,只需要更少的存儲空間、更少的內存分配,而且指針操作比其他間接操作的語言也更有效率

  • 并發支持

  • 由于現代計算機是一個并行的機器,Go語言提供了基于CSP的并發特性支持。Go語言的動態棧使得輕量級線程goroutine的初始棧可以很小,因此創建一個goroutine的代價很小,創建百萬級的goroutine完全是可行的。

  • Go并發的座右銘:不要通過共享內存進行通信,而要通過通信共享內存(Don't communicate by sharing memory, share memory by communicating)

  • 自動垃圾回收機制

  • 對于系統語言,垃圾回收可能是一個有爭議的功能

  • Go沒有顯式的內存釋放操作:分配的內存返回池的唯一方法是通過垃圾回收器。

  • 內存管理對語言在實踐中的工作方式具有深遠的影響。在C和C++中,太多的編程工作花費在內存分配和釋放上

  • 由于垃圾回收機制,語言更易于使用。

  • 垃圾回收會帶來巨大的成本:常規開銷,延遲和實現的復雜性

  • 知識淵博的程序員可以限制收集器所承受的壓力,從而提高性能。(此外,Go安裝附帶了用于研究正在運行的程序的動態內存性能的良好工具)

  • 自動垃圾回收算法是一個持續跟新的過程、活躍的開發領域

  • 強大的標準庫與規范

  • Go語言的標準庫,提供了清晰的構建模塊和公共接口,包含I/O操作、文本處理、圖像、密碼學、網絡和分布式應用程序等,并支持許多標準化的文件格式和編解碼協議

  • 庫和工具使用了大量的約定來減少額外的配置和解釋,從而最終簡化程序的邏輯,而且每個Go程序結構都是如此的相似,因此Go程序也很容易學習

  • Go語言自帶工具構建Go語言項目只需要使用文件名、標識符名稱以及少量的注釋確定所有的庫、可執行文件、測試、基準測試、案例、以及特定于平臺的變量、項目的文檔等;Go語言源代碼本身就包含了構建規范

  • 開源,活躍的社區

  • 組成而不是繼承

  • Go采用一種不尋常的方法來進行面向對象的編程(接口),它允許有相同方法的任何類型繼承,而不僅是類

  • Go沒有任何形式的基于類型的繼承,這意味著沒有類型層次結構

  • 這是一個故意的設計選擇,盡管類型層次結構已用于構建許多成功的軟件,但Go認為該模型已被過度使用

Go語言的優勢

  • 學習曲線容易,語法簡單清晰

  • 單就類型和規則而言,Go 與 C99、C11 相似之處頗多,這也是Go語言被冠以“NextC”名號的重要原因。

  • Go語言的語法規則嚴謹,沒有歧義,更沒什么黑魔法變異用法。

  • 任何人寫出的代碼都基本一致,這使得Go語言簡單易學。放棄部分“靈活”和“自由”,換來更好的維護性

  • 強大的標準庫和工具鏈

  • 完整的工具鏈對于日常開發極為重要。Go 在此做得相當不錯,無論是編譯、格式化、錯誤檢查、幫助文檔,還是第三方包下載、更新都有對應的工具

  • 內置完整測試框架,其中包括單元測試、性能測試、代碼覆蓋率、數據競爭,以及用來調優的 pprof,這些都是保障代碼能正確而穩定運行的必備利器

  • 可通過環境變量輸出運行時監控信息,尤其是垃圾回收和并發調度跟蹤,可進一步幫助我們改進算法,獲得更佳的運行期表現

  • 自動垃圾回收機制

  • 垃圾回收一直是個難題。早年間,Java 就因垃圾回收低效被嘲笑了許久,后來 Sun 連續收納了好多人和技術才發展到今天。可即便如此,在 Hadoop 等大內存應用場景下,垃圾回收依舊捉襟見肘、步履維艱

  • 相比 Java,Go 面臨的困難要更多。因指針的存在,所以回收內存不能做收縮處理。幸好,指針運算被阻止,否則要做到精確回收都難

  • 每次升級,垃圾回收器必然是核心組件里修改最多的部分。從并發清理,到降低 STW 時間,直到 Go 的 1.5 版本實現并發標記,逐步引入三色標記和寫屏障等等,都是為了能讓垃圾回收在不影響用戶邏輯的情況下更好地工作

  • 靜態鏈接
    運行時、依賴庫直接打包到可執行文件內部,簡化了部署和發布操作,無須事先安裝運行環境和下載諸多第三方庫

  • 編譯迅速

  • 清晰的依賴關系

  • 并發編程

  • 在早期 CPU 都是以單核的形式順序執行機器指令。Go語言的祖先C語言正是這種順序編程語言的代表

  • 隨著處理器技術的發展,單核時代以提升處理器頻率來提高運行效率的方式遇到了瓶頸,單核 CPU 發展的停滯,給多核 CPU 的發展帶來了機遇

  • 現代計算機都擁有多個核,但是大部分編程語言都沒有有效的工具讓程序可以輕易利用這些資源。編程時需要寫大量的線程同步代碼來利用多個核,很容易導致錯誤

  • Go語言正是在多核和網絡化的時代背景下誕生的原生支持并發的編程語言。Go語言從底層原生支持并發,無須第三方庫,開發人員可以很輕松地在編寫程序時決定怎么使用 CPU 資源

  • Goroutine 是 Go 最顯著的特征

  • Go語言的并發是基于 goroutine 的,goroutine 類似于線程,但并非線程。可以將 goroutine 理解為一種虛擬線程。Go語言運行時會參與調度 goroutine,并將 goroutine 合理地分配到每個 CPU 中,最大限度地使用 CPU 性能

  • Go用類協程的方式來處理并發單元,卻又在運行時層面做了更深度的優化處理。這使得語法上的并發編程變得極為容易

  • 無須處理回調,無須關注線程切換,僅一個關鍵字,簡單而自然

  • 搭配 channel,實現 CSP 模型。將并發單元間的數據耦合拆解開來,各司其職,這對所有糾結于內存共享、鎖粒度的開發人員都是一個可期盼的解脫

  • 內存分配

  • Go 選擇了 tcmalloc,它本就是為并發而設計的高性能內存分配組件

  • 刨去因配合垃圾回收器而修改的內容,內存分配器完整保留了 tcmalloc 的原始架構。使用 cache 為當前執行線程提供無鎖分配,多個 central 在不同線程間平衡內存單元復用

  • heap 則管理著大塊內存,用以切分成不同等級的復用內存塊。快速分配和二級內存平衡機制,讓內存分配器能優秀地完成高壓力下的內存管理任務

Go語言擅長的領域

  • Go語言主要用作服務器端開發,適合于多人周期較長的大型軟件和支持云計算的網絡服務
  • 在服務器編程方面,Go語言適合處理日志、中間件、數據打包、虛擬機處理、文件系統、分布式系統、數據庫代理等
  • 網絡編程方面,Go語言廣泛應用于 Web 應用、API 應用、下載應用等
  • 此外,Go語言還可用于內存數據庫和云平臺領域,目前國外很多云平臺都是采用 Go 開發
  • 由于Go垃圾回收犧牲了一些性能,因此其不適合做操作系統編程以及對速度要求極致的程序,不適合直接處理數據分析與計算

使用Go語言的公司

參見世界上使用Go語言的企業

  • Google

  • 作為創造了Go語言的 google 公司,當然會力挺Go語言了。Google 有很多基于 Go 開發的開源項目,比如 kubernets,docker,大家可以參考《哪些項目使用Go語言開發》一節了解更多的Go語言開源項目

  • Facebook

  • Facebook 也在使用Go語言,為此他們還專門在 Github 上建立了一個開源組織 facebookgo。大家可以通過 https://github.com/facebookgo 訪問查看 facebook 開源的項目,其中最具代表性的就是著名平滑重啟工具 grace

  • 騰訊

  • 騰訊在 15 年就已經做了 Docker 萬臺規模的實踐。因為騰訊主要的開發語言是 C/C++ ,所以在使用Go語言方面會方便很多,也有很多優勢,不過日積月累的 C/C++ 代碼很難改造,也不敢動,所以主要在新業務上嘗試使用 Go

  • 百度

  • 百度主要在運維方面使用到了Go語言,比如百度運維的一個 BFE 項目,主要負責前端流量的接入,其次就是百度消息通訊系統的服務器端也使用到了Go語言

  • 七牛云

  • 七牛云算是國內第一家選Go語言做服務端的公司。早在 2011 年,當Go語言的語法還沒完全穩定下來的情況下,七牛云就已經選擇將 Go 作為存儲服務端的主體語言

  • 京東

  • 京東云消息推送系統、云存儲,以及京東商城的列表頁等都是使用Go語言開發的

  • 小米

  • 小米對Go語言的支持,在于運維監控系統的開源,它的官方網址是 http://open-falcon.org/。此外,小米互娛、小米商城、小米視頻、小米生態鏈等團隊都在使用Go語言

  • 360

  • 360 對Go語言的使用也不少,比如開源的日志搜索系統 Poseidon,大家可以通過 https://github.com/Qihoo360/poseidon 查看,還有 360 的推送團隊也在使用Go語言
    除了上面提到的,還有很多公司開始嘗試使用Go語言,比如美團、滴滴、新浪等。

Go語言吉祥物

Go語言有一個吉祥物,在會議、文檔頁面和博文中,大多會包含下圖所示的 Go Gopher,這是才華橫溢的插畫家 Renee French 設計的,她也是 Go 設計者之一 Rob Pike 的妻子。

image

參考資料

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,725評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,695評論 2 370

推薦閱讀更多精彩內容