鍍金池/ 教程/ GO/ 1.2 語言的主要特性與發(fā)展的環(huán)境和影響因素
4.7 strings 和 strconv 包
13.6 啟動外部命令和程序
?# 11.4 類型判斷:type-switch
12.1 讀取用戶的輸入
10.6 方法
12.2 文件讀寫
13 錯誤處理與測試
9.3 鎖和 sync 包
12.3 文件拷貝
?# 11.7 第一個例子:使用 Sorter 接口排序
?# 11.5 測試一個值是否實現(xiàn)了某個接口
6.4 defer 和追蹤
12.10 XML 數(shù)據(jù)格式
13.10 性能調(diào)試:分析并優(yōu)化 Go 程序
?# 11.1 接口是什么
2.2 Go 環(huán)境變量
2.6 安裝目錄清單
2.5 在 Windows 上安裝 Go
11.11 Printf 和反射
1.2 語言的主要特性與發(fā)展的環(huán)境和影響因素
9.0 包(package)
7.4 切片重組(reslice)
13.2 運行時異常和 panic
10.2 使用工廠方法創(chuàng)建結(jié)構(gòu)體實例
12.8 使用接口的實際例子:fmt.Fprintf
2.4 在 Mac OS X 上安裝 Go
3.8 Go 性能說明
7.2 切片
8.0 Map
3.1 Go 開發(fā)環(huán)境的基本要求
5.6 標(biāo)簽與 goto
6.10 使用閉包調(diào)試
9.5 自定義包和可見性
4.3 常量
?# 11.2 接口嵌套接口
6.5 內(nèi)置函數(shù)
前言
10.8 垃圾回收和 SetFinalizer
2.8 Go 解釋器
13.7 Go 中的單元測試和基準(zhǔn)測試
6.8 閉包
4.9 指針
13.1 錯誤處理
10.1 結(jié)構(gòu)體定義
5.1 if-else 結(jié)構(gòu)
6.6 遞歸函數(shù)
9.9 通過 Git 打包和安裝
2.7 Go 運行時(runtime)
10.7 類型的 String() 方法和格式化描述符
3.7 其它工具
9.6 為自定義包使用 godoc
11.12 接口與動態(tài)類型
13.3 從 panic 中恢復(fù)(Recover)
10.3 使用自定義包中的結(jié)構(gòu)體
11.14 結(jié)構(gòu)體、集合和高階函數(shù)
3.6 生成代碼文檔
9.2 regexp 包
4.1 文件名、關(guān)鍵字與標(biāo)識符
?# 11.6 使用方法集與接口
7.0 數(shù)組與切片
7.1 聲明和初始化
12.11 用 Gob 傳輸數(shù)據(jù)
5.5 Break 與 continue
1.1 起源與發(fā)展
?# 11 接口(Interfaces)與反射(reflection)
6.9 應(yīng)用閉包:將函數(shù)作為返回值
4.2 Go 程序的基本結(jié)構(gòu)和要素
8.6 將 map 的鍵值對調(diào)
6.11 計算函數(shù)執(zhí)行時間
5.0 控制結(jié)構(gòu)
10.5 匿名字段和內(nèi)嵌結(jié)構(gòu)體
4.6 字符串
3.0 編輯器、集成開發(fā)環(huán)境與其它工具
13.8 測試的具體例子
7.6 字符串、數(shù)組和切片的應(yīng)用
8.4 map 類型的切片
3.9 與其它語言進(jìn)行交互
7.3 For-range 結(jié)構(gòu)
9.7 使用 go install 安裝自定義包
6.0 函數(shù)
9.8 自定義包的目錄結(jié)構(gòu)、go install 和 go test
6.3 傳遞變長參數(shù)
13.9 用(測試數(shù)據(jù))表驅(qū)動測試
11.9 空接口
8.1 聲明、初始化和 make
6.2 函數(shù)參數(shù)與返回值
9.11 在 Go 程序中使用外部庫
3.3 調(diào)試器
4.5 基本類型和運算符
?# 11.8 第二個例子:讀和寫
12.5 用 buffer 讀取文件
總結(jié):Go 中的面向?qū)ο?/span>
11.10 反射包
12.7 用 defer 關(guān)閉文件
9.4 精密計算和 big 包
4.4 變量
6.1 介紹
13.4 自定義包中的錯誤處理和 panicking
12.4 從命令行讀取參數(shù)
9.10 Go 的外部包和項目
8.3 for-range 的配套用法
3.5 格式化代碼
10.4 帶標(biāo)簽的結(jié)構(gòu)體
7.5 切片的復(fù)制與追加
?# 11.3 類型斷言:如何檢測和轉(zhuǎn)換接口變量的類型
5.4 for 結(jié)構(gòu)
4.8 時間和日期
2.3 在 Linux 上安裝 Go
12 讀寫數(shù)據(jù)
6.12 通過內(nèi)存緩存來提升性能
9.1 標(biāo)準(zhǔn)庫概述
12.6 用切片讀寫文件
10 結(jié)構(gòu)(struct)與方法(method)
8.5 map 的排序
12.9 JSON 數(shù)據(jù)格式
13.5 一種用閉包處理錯誤的模式
3.2 編輯器和集成開發(fā)環(huán)境
12.12 Go 中的密碼學(xué)
5.2 測試多返回值函數(shù)的錯誤
6.7 將函數(shù)作為參數(shù)
8.2 測試鍵值對是否存在及刪除元素
3.4 構(gòu)建并運行 Go 程序
2.1 平臺與架構(gòu)
5.3 switch 結(jié)構(gòu)

1.2 語言的主要特性與發(fā)展的環(huán)境和影響因素

1.2.1 影響 Go 語言發(fā)展的早期編程語言

正如 “21 世紀(jì)的 C 語言” 這句話所說,Go 語言并不是憑空而造的,而是和 C++、Java 和 C# 一樣屬于 C 系。不僅如此,設(shè)計者們還汲取了其它編程語言的精粹部分融入到 Go 語言當(dāng)中。

在聲明和包的設(shè)計方面,Go 語言受到 Pascal、Modula 和 Oberon 系語言的影響;在并發(fā)原理的設(shè)計上,Go 語言從同樣受到 Tony Hoare 的 CSP(通信序列進(jìn)程 Communicating Squential Processes)理論影響的 Limbo 和 Newsqueak 的實踐中借鑒了一些經(jīng)驗,并使用了和 Erlang 類似的機(jī)制。

這是一門完全開源的編程語言,因為它使用 BSD 授權(quán)許可,所以任何人都可以進(jìn)行商業(yè)軟件的開發(fā)而不需要支付任何費用。

盡管為了能夠讓目前主流的開發(fā)者們能夠?qū)?Go 語言中的類 C 語言的語法感到非常親切而易于轉(zhuǎn)型,但是它在極大程度上簡化了這些語法,使得它們比 C/C++ 的語法更加簡潔和干凈。同時,Go 語言也擁有一些動態(tài)語言的特性,這使得使用 Python 和 Ruby 的開發(fā)者們在使用 Go 語言的時候感覺非常容易上手。

下圖展示了一些其它編程語言對 Go 語言的影響:

http://wiki.jikexueyuan.com/project/the-way-to-go/images/1.3.influences_on_go.jpg?raw=true" alt="" />

圖 1.3 其它編程語言對 Go 語言的影響

1.2.2 為什么要創(chuàng)造一門編程語言

  • C/C++ 的發(fā)展速度無法跟上計算機(jī)發(fā)展的腳步,十多年來也沒有出現(xiàn)一門與時代相符的主流系統(tǒng)編程語言,因此人們需要一門新的系統(tǒng)編程語言來彌補這個空缺,尤其是在計算機(jī)信息時代。
  • 對比計算機(jī)性能的提升,軟件開發(fā)領(lǐng)域不被認(rèn)為發(fā)展地足夠快或者比硬件發(fā)展更加成功(有許多項目均以失敗告終),同時應(yīng)用程序的體積始終在不斷地擴(kuò)大,這就迫切地需要一門具備更高層次概念的低級語言來突破現(xiàn)狀。
  • 在 Go 語言出現(xiàn)之前,開發(fā)者們總是面臨非常艱難的抉擇,究竟是使用執(zhí)行速度快但是編譯速度并不理想的語言(如:C++),還是使用編譯速度較快但執(zhí)行效率不佳的語言(如:.NET、Java),或者說開發(fā)難度較低但執(zhí)行速度一般的動態(tài)語言呢?顯然,Go 語言在這 3 個條件之間做到了最佳的平衡:快速編譯,高效執(zhí)行,易于開發(fā)。

1.2.3 Go 語言的發(fā)展目標(biāo)

Go 語言的主要目標(biāo)是將靜態(tài)語言的安全性和高效性與動態(tài)語言的易開發(fā)性進(jìn)行有機(jī)結(jié)合,達(dá)到完美平衡,從而使編程變得更加有樂趣,而不是在艱難抉擇中痛苦前行。

因此,Go 語言是一門類型安全和內(nèi)存安全的編程語言。雖然 Go 語言中仍有指針的存在,但并不允許進(jìn)行指針運算。

Go 語言的另一個目標(biāo)是對于網(wǎng)絡(luò)通信、并發(fā)和并行編程的極佳支持,從而更好地利用大量的分布式和多核的計算機(jī),這一點對于谷歌內(nèi)部的使用來說就非常重要了。設(shè)計者通過 goroutine 這種輕量級線程的概念來實現(xiàn)這個目標(biāo),然后通過 channel 來實現(xiàn)各個 goroutine 之間的通信。他們實現(xiàn)了分段棧增長和 goroutine 在線程基礎(chǔ)上多路復(fù)用技術(shù)的自動化。

這個特性顯然是 Go 語言最強(qiáng)有力的部分,不僅支持了日益重要的多核與多處理器計算機(jī),也彌補了現(xiàn)存編程語言在這方面所存在的不足。

Go 語言中另一個非常重要的特性就是它的構(gòu)建速度(編譯和鏈接到機(jī)器代碼的速度),一般情況下構(gòu)建一個程序的時間只需要數(shù)百毫秒到幾秒。作為大量使用 C++ 來構(gòu)建基礎(chǔ)設(shè)施的谷歌來說,無疑從根本上擺脫了 C++ 在構(gòu)建速度上非常不理想的噩夢。這不僅極大地提升了開發(fā)者的生產(chǎn)力,同時也使得軟件開發(fā)過程中的代碼測試環(huán)節(jié)更加緊湊,而不必浪費大量的時間在等待程序的構(gòu)建上。

依賴管理是現(xiàn)今軟件開發(fā)的一個重要組成部分,但是 C 語言中“頭文件”的概念卻導(dǎo)致越來越多因為依賴關(guān)系而使得構(gòu)建一個大型的項目需要長達(dá)幾個小時的時間。人們越來越需要一門具有嚴(yán)格的、簡潔的依賴關(guān)系分析系統(tǒng)從而能夠快速編譯的編程語言。這正是 Go 語言采用包模型的根本原因,這個模型通過嚴(yán)格的依賴關(guān)系檢查機(jī)制來加快程序構(gòu)建的速度,提供了非常好的可量測性。

整個 Go 語言標(biāo)準(zhǔn)庫的編譯時間一般都在 20 秒以內(nèi),其它的常規(guī)項目也只需要半秒鐘的時間來完成編譯工作。這種閃電般的編譯速度甚至比編譯 C 語言或者 Fortran 更加快,使得編譯這一環(huán)節(jié)不再成為在軟件開發(fā)中困擾開發(fā)人員的問題。在這之前,動態(tài)語言將快速編譯作為自身的一大亮點,像 C++ 那樣的靜態(tài)語言一般都有非常漫長的編譯和鏈接工作。而同樣作為靜態(tài)語言的 Go 語言,通過自身優(yōu)良的構(gòu)建機(jī)制,成功地去除了這個弊端,使得程序的構(gòu)建過程變得微不足道,擁有了像腳本語言和動態(tài)語言那樣的高效開發(fā)的能力。

另外,Go 語言在執(zhí)行速度方面也可以與 C/C++ 相提并論。

由于內(nèi)存問題(通常稱為內(nèi)存泄漏)長期以來一直伴隨著 C++ 的開發(fā)者們,Go 語言的設(shè)計者們認(rèn)為內(nèi)存管理不應(yīng)該是開發(fā)人員所需要考慮的問題。因此盡管 Go 語言像其它靜態(tài)語言一樣執(zhí)行本地代碼,但它依舊運行在某種意義上的虛擬機(jī),以此來實現(xiàn)高效快速的垃圾回收(使用了一個簡單的標(biāo)記-清除算法)。

盡管垃圾回收并不容易實現(xiàn),但考慮這將是未來并發(fā)應(yīng)用程序發(fā)展的一個重要組成部分,Go 語言的設(shè)計者們還是完成了這項艱難的任務(wù)。

Go 語言還能夠在運行時進(jìn)行反射相關(guān)的操作。

使用 go install 能夠很輕松地對第三方包進(jìn)行部署。

此外,Go 語言還支持調(diào)用由 C 語言編寫的海量庫文件(第 3.9 節(jié)),從而能夠?qū)⑦^去開發(fā)的軟件進(jìn)行快速遷移。

1.2.4 指導(dǎo)設(shè)計原則

Go語言通過減少關(guān)鍵字的數(shù)量(25 個)來簡化編碼過程中的混亂和復(fù)雜度。干凈、整齊和簡潔的語法也能夠提高程序的編譯速度,因為這些關(guān)鍵字在編譯過程中少到甚至不需要符號表來協(xié)助解析。

這些方面的工作都是為了減少編碼的工作量,甚至可以與 Java 的簡化程度相比較。

Go 語言有一種極簡抽象藝術(shù)家的感覺,因為它只提供了一到兩種方法來解決某個問題,這使得開發(fā)者們的代碼都非常容易閱讀和理解。眾所周知,代碼的可讀性是軟件工程里最重要的一部分( 譯者注:代碼是寫給人看的,不是寫給機(jī)器看的 )。

這些設(shè)計理念沒有建立其它概念之上,所以并不會因為牽扯到一些概念而將某個概念復(fù)雜化,他們之間是相互獨立的。

Go 語言有一套完整的編碼規(guī)范,你可以在 Go 語言編碼規(guī)范 頁面進(jìn)行查看。

它不像 Ruby 那樣通過實現(xiàn)過程來定義編碼規(guī)范。作為一門具有明確編碼規(guī)范的語言,它要求可以采用不同的編譯器如 gc 和 gccgo(第 2.1 節(jié))進(jìn)行編譯工作,這對語言本身擁有更好的編碼規(guī)范起到很大幫助。

LALR 是 Go 語言的語法標(biāo)準(zhǔn),你也可以在 src/cmd/internal/gc/go.y 中查看到,這種語法標(biāo)準(zhǔn)在編譯時不需要符號表來協(xié)助解析。

1.2.5 語言的特性

Go 語言從本質(zhì)上(程序和結(jié)構(gòu)方面)來實現(xiàn)并發(fā)編程。

因為 Go 語言沒有類和繼承的概念,所以它和 Java 或 C++ 看起來并不相同。但是它通過接口(interface)的概念來實現(xiàn)多態(tài)性。Go 語言有一個清晰易懂的輕量級類型系統(tǒng),在類型之間也沒有層級之說。因此可以說這是一門混合型的語言。

在傳統(tǒng)的面向?qū)ο笳Z言中,使用面向?qū)ο缶幊碳夹g(shù)顯得非常臃腫,它們總是通過復(fù)雜的模式來構(gòu)建龐大的類型層級,這違背了編程語言應(yīng)該提升生產(chǎn)力的宗旨。

函數(shù)是 Go 語言中的基本構(gòu)件,它們的使用方法非常靈活。在第六章,我們會看到 Go 語言在函數(shù)式編程方面的基本概念。

Go 語言使用靜態(tài)類型,所以它是類型安全的一門語言,加上通過構(gòu)建到本地代碼,程序的執(zhí)行速度也非??臁?/p>

作為強(qiáng)類型語言,隱式的類型轉(zhuǎn)換是不被允許的,記住一條原則:讓所有的東西都是顯式的。

Go 語言其實也有一些動態(tài)語言的特性(通過關(guān)鍵字 var),所以它對那些逃離 Java 和 .Net 世界而使用 Python、Ruby、PHP 和 JavaScript 的開發(fā)者們也具有很大的吸引力。

Go 語言支持交叉編譯,比如說你可以在運行 Linux 系統(tǒng)的計算機(jī)上開發(fā)運行下 Windows 下運行的應(yīng)用程序。這是第一門完全支持 UTF-8 的編程語言,這不僅體現(xiàn)在它可以處理使用 UTF-8 編碼的字符串,就連它的源碼文件格式都是使用的 UTF-8 編碼。Go 語言做到了真正的國際化!

1.2.6 語言的用途

Go 語言被設(shè)計成一門應(yīng)用于搭載 Web 服務(wù)器,存儲集群或類似用途的巨型中央服務(wù)器的系統(tǒng)編程語言。對于高性能分布式系統(tǒng)領(lǐng)域而言,Go 語言無疑比大多數(shù)其它語言有著更高的開發(fā)效率。它提供了海量并行的支持,這對于游戲服務(wù)端的開發(fā)而言是再好不過了。

Go 語言一個非常好的目標(biāo)就是實現(xiàn)所謂的復(fù)雜事件處理(CEP),這項技術(shù)要求海量并行支持,高度的抽象化和高性能。當(dāng)我們進(jìn)入到物聯(lián)網(wǎng)時代,CEP 必然會成為人們關(guān)注的焦點。

但是 Go 語言同時也是一門可以用于實現(xiàn)一般目標(biāo)的語言,例如對于文本的處理,前端展現(xiàn),甚至像使用腳本一樣使用它。

值得注意的是,因為垃圾回收和自動內(nèi)存分配的原因,Go 語言不適合用來開發(fā)對實時性要求很高的軟件。

越來越多的谷歌內(nèi)部的大型分布式應(yīng)用程序都開始使用 Go 語言來開發(fā),例如谷歌地球的一部分代碼就是由 Go 語言完成的。

如果你想知道一些其它組織使用Go語言開發(fā)的實際應(yīng)用項目,你可以到 使用 Go 的組織 頁面進(jìn)行查看。出于隱私保護(hù)的考慮,許多公司的項目都沒有展示在這個頁面。我們將會在第 21 章討論到一個使用 Go 語言開發(fā)的大型存儲區(qū)域網(wǎng)絡(luò)(SAN)案例。

在 Chrome 瀏覽器中內(nèi)置了一款 Go 語言的編譯器用于本地客戶端(NaCl),這很可能會被用于在 Chrome OS 中執(zhí)行 Go 語言開發(fā)的應(yīng)用程序。

Go 語言可以在 Intel 或 ARM 處理器上運行,因此它也可以在安卓系統(tǒng)下運行,例如 Nexus 系列的產(chǎn)品。

在 Google App Engine 中使用 Go 語言:2011 年 5 月 5 日,官方發(fā)布了用于開發(fā)運行在 Google App Engine 上的 Web 應(yīng)用的 Go SDK,在此之前,開發(fā)者們只能選擇使用 Python 或者 Java。這主要是 David Symonds 和 Nigel Tao 努力的成果。目前最新的穩(wěn)定版是基于 Go 1.4 的 SDK 1.9.18,于 2015 年 2 月 18 日發(fā)布。當(dāng)前 Go 語言的穩(wěn)定版本是 Go 1.4.2。

1.2.7 關(guān)于特性缺失

許多能夠在大多數(shù)面向?qū)ο笳Z言中使用的特性 Go 語言都沒有支持,但其中的一部分可能會在未來被支持。

  • 為了簡化設(shè)計,不支持函數(shù)重載和操作符重載
  • 為了避免在 C/C++ 開發(fā)中的一些 Bug 和混亂,不支持隱式轉(zhuǎn)換
  • Go 語言通過另一種途徑實現(xiàn)面向?qū)ο笤O(shè)計(第 10-11 章)來放棄類和類型的繼承
  • 盡管在接口的使用方面(第 11 章)可以實現(xiàn)類似變體類型的功能,但本身不支持變體類型
  • 不支持動態(tài)加載代碼
  • 不支持動態(tài)鏈接庫
  • 不支持泛型
  • 通過 recoverpanic 來替代異常機(jī)制(第 13.2-3 節(jié))
  • 不支持?jǐn)嘌?/li>
  • 不支持靜態(tài)變量

關(guān)于 Go 語言開發(fā)團(tuán)隊對于這些方面的討論,你可以通過 Go 常見問題 頁面查看。

1.2.8 使用 Go 語言編程

如果你有其它語言的編程經(jīng)歷(面向?qū)ο缶幊陶Z言,如:Java、C#、Object-C、Python、Ruby),在你進(jìn)入到 Go 語言的世界之后,你將會像迷戀你的 X 語言一樣無法自拔。Go 語言使用了與其它語言不同的設(shè)計模式,所以當(dāng)你嘗試將你的X語言的代碼遷移到 Go 語言時,你將會非常失望,所以你需要從頭開始,用 Go 的理念來思考。

如果你在至高點使用 Go 的理念來重新審視和分析一個問題,你通常會找到一個適用于 Go 語言的優(yōu)雅的解決方案。

1.2.9 小結(jié)

這里列舉一些 Go 語言的必殺技:

  • 簡化問題,易于學(xué)習(xí)
  • 內(nèi)存管理,簡潔語法,易于使用
  • 快速編譯,高效開發(fā)
  • 高效執(zhí)行
  • 并發(fā)支持,輕松駕馭
  • 靜態(tài)類型
  • 標(biāo)準(zhǔn)類庫,規(guī)范統(tǒng)一
  • 易于部署
  • 文檔全面
  • 免費開源

鏈接