一、簡介
Go(又稱Golang)是Google開發(fā)的一種靜態(tài)強類型硬鞍、編譯型、并發(fā)型戴已,并具有垃圾回收功能的編程語言固该。Go于2009年11月正式宣布推出,成為開放源代碼項目糖儡,支持Linux伐坏、macOS、Windows等操作系統(tǒng)握联。
1.Go 語言的目標與意義
-
Go 語言的主要目標是將靜態(tài)語言的安全性和高效性與動態(tài)語言的易開發(fā)性進行有機結合桦沉,達到完美平衡。
- Go 語言是一門類型安全和內存安全的編程語言金闽。雖然 Go 語言中仍有指針的存在纯露,但并不允許進行指針運算。
-
Go 語言的另一個目標是對于網絡通信代芜、并發(fā)和并行編程的極佳支持埠褪,從而更好地利用大量的分布式和多核的計算機。
- 通過 goroutine 這種輕量級線程的概念來實現(xiàn)這個目標挤庇,然后通過 channel 來實現(xiàn)各個 goroutine 之間的通信钞速。
Go 語言的構建速度(編譯和鏈接到機器代碼的速度),一般情況下構建一個程序的時間只需要數百毫秒到幾秒嫡秕。
-
Go 語言不需要開發(fā)人員需要考慮內存問題(內存泄漏)
- Go 語言像其它靜態(tài)語言一樣執(zhí)行本地代碼渴语,但它依舊運行在某種意義上的虛擬機,以此來實現(xiàn)高效快速的垃圾回收(使用了一個簡單的標記-清除算法)昆咽。
Go 語言支持調用由 C 語言編寫的海量庫文件遵班,從而能夠將過去開發(fā)的軟件進行快速遷移。
2.與其他語言的比較
Go的語法接近C語言潮改,但對于變量的聲明有所不同狭郑。Go支持垃圾回收功能。Go的并行計算模型是以通信順序進程(CSP)為基礎汇在,采取類似模型的其他語言包括Occam和Limbo翰萨,[2],但它也具有pipeline模型的特征糕殉,比如通道傳輸亩鬼。在1.8版本中開放插件(Plugin)的支持殖告,這意味著現(xiàn)在能從Go中動態(tài)加載部分函數。
與C++相比雳锋,Go并不包括如枚舉黄绩、異常處理、繼承玷过、泛型爽丹、斷言、虛函數等功能辛蚊,但增加了 切片(Slice) 型粤蝎、并發(fā)、管道袋马、垃圾回收功能初澎、接口等特性的語言級支持。
不同于Java虑凛,Go原生提供了關聯(lián)數組(也稱為哈希表(Hashes)或字典(Dictionaries))碑宴,就像字符串類型一樣。
3.Go的缺失特性
- 為了簡化設計桑谍,不支持函數重載和操作符重載
- 為了避免在 C/C++ 開發(fā)中的一些 Bug 和混亂延柠,不支持隱式轉換
- Go 語言通過另一種途徑實現(xiàn)面向對象設計來放棄類和類型的繼承
- 盡管在接口的使用方面可以實現(xiàn)類似變體類型的功能,但本身不支持變體類型
- 不支持動態(tài)加載代碼
- 不支持動態(tài)鏈接庫
- 不支持泛型
- 通過
recover
和panic
來替代異常機制(第 13.2-3 節(jié)) - 不支持靜態(tài)變量
二霉囚、Go項目風格
1.撰寫風格
- 每行程序結束后不需要撰寫分號(;)捕仔。
- 大括號({)不能夠換行放置。
- 換行會產生編譯錯誤
- if判斷式和for循環(huán)不需要以小括號包覆起來盈罐。
- 使用 tab 做排版
備注:除了第二點外榜跌,在不符合上述規(guī)定時,仍舊可以編譯盅粪,但使用了內置gofmt工具后钓葫,會自動整理代碼,使之符合規(guī)定的撰寫風格票顾。
2.項目架構
所有Go項目代碼都應該保存在一個工作區(qū)中础浮;
工作區(qū)包含許多版本控制存儲庫 ;
每個存儲庫包含一個或多個軟件包奠骄;
每個軟件包都在一個目錄中包含一個或多個Go源文件豆同。
1)Go的工作區(qū)的目錄結構
$GOPATH路徑下
目錄 | 用途 |
---|---|
src | Go源代碼 |
pkg | 編譯時,生成的對象文件 |
bin | 編譯后的程序 |
注意 當創(chuàng)建目錄時含鳞,文件夾名稱永遠不應該包含空格影锈,而應該使用下劃線 "_" 或者其它一般符號代替。
項目目錄示例
bin/
hello # 生成的執(zhí)行檔
outyet # 生成的執(zhí)行檔
pkg/
linux_amd64/
github.com/golang/example/
stringutil.a # 編譯時,生成的對象檔案
src/
github.com/golang/example/
.git/ # 外部 Git 庫的詮釋資料
hello/
hello.go # Git 庫的程式碼
outyet/
main.go # Git 庫的程式碼
main_test.go # Git 庫的程式碼(測試用的程式)
stringutil/
reverse.go # Git 庫的程式碼
reverse_test.go # Git 庫的程式碼(測試用的程式)
golang.org/x/image/
.git/ # 外部 Git 庫的詮釋資料
bmp/
reader.go # Git 庫的程式碼
writer.go # Git 庫的程式碼
2)編譯器
當前有兩個Go編譯器分支鸭廷,分別為官方編譯器gc和gccgo枣抱。
-
官方編譯器在初期使用C寫成,后用Go重寫從而實現(xiàn)自舉辆床。
官方編譯器支持跨平臺編譯(但不支持CGO)佳晶,允許將源代碼編譯為可在目標系統(tǒng)、架構上執(zhí)行的二進制文件讼载。
-
編譯器目前支持以下基于 Intel 或 AMD 處理器架構的程序構建轿秧。
g = 編譯器:將源代碼編譯為項目代碼(程序文本) l = 鏈接器:將項目代碼鏈接到可執(zhí)行的二進制文件(機器代碼)
- 相關的 C 編譯器名稱為 6c、8c 和 5c维雇,相關的匯編器名稱為 6a淤刃、8a 和 5a
-
Gccgo是一個使用標準GCC作為后端的Go編譯器晒他。
- 能夠構建基于眾多處理器架構的應用程序吱型。編譯速度相對 gc 較慢,但產生的本地代碼運行要稍微快一點陨仅。它同時也提供一些與 C 語言之間的互操作性津滞。
3)文件擴展名與包(package)
- Go 語言源文件的擴展名就是
.go
。C 文件使用后綴名.c
灼伤,匯編文件使用后綴名.s
触徐。 - 所有的源代碼文件都是通過包(packages)來組織。包含可執(zhí)行代碼的包文件在被壓縮后使用擴展名
.a
(AR 文檔)狐赡。Go 語言的標準庫 包文件在被安裝后就是使用這種格式的文件撞鹉。
三、Go運行環(huán)境與軟件安裝
1.支持的平臺與架構
- Linux 2.6+:amd64颖侄、386 和 arm 架構
- Mac OS X(Snow Leopard + Lion):amd64 和 386 架構
- Windows 2000+:amd64 和 386 架構
2.環(huán)境變量
重要的環(huán)境變量
-
$GOROOT 表示 Go 在你的電腦上的安裝位置鸟雏,它的值一般都是
$HOME/go
。 - $GOARCH 表示目標機器的處理器架構览祖,它的值可以是 386(x86的一部分)孝鹊、amd64 或 arm。
- $GOOS 表示目標機器的操作系統(tǒng)展蒂,它的值可以是 darwin又活、freebsd、linux 或 windows锰悼。
-
$GOBIN 表示編譯器和鏈接器的安裝位置柳骄,默認是
$GOROOT/bin
- 如果是 Go 1.0.3 及以后的版本,一般情況下可以將它的值設置為空箕般,Go 將會使用前面提到的默認值耐薯。
- $GOHOSTARCH 表示本地機器的處理器架構,它的值可以是 386(x86的一部分)、amd64 或 arm可柿。
- $GOHOSTOS 表示本地機器的操作系統(tǒng)鸠踪,它的值可以是 darwin、freebsd复斥、linux 或 windows营密。
-
$GOPATH 表示 Go 的工作區(qū),該目錄下必須包含三個規(guī)定的目錄:
src
目锭、pkg
和bin
评汰,這三個目錄分別用于存放源碼文件、包文件和可執(zhí)行文件痢虹。 - $GOARM 專門針對基于 arm 架構的處理器被去,它的值可以是 5 或 6,默認為 6奖唯。
- $GOMAXPROCS 用于設置應用程序可使用的處理器個數與核數惨缆。
備注:
$GOHOSTOS
和$GOHOSTARCH
這兩個變量只有在進行交叉編譯的時候才會用到,如果不進行設置丰捷,它們的值會和$GOOS
和$GOARCH
一樣坯墨。
通過修改$HOME/.bashrc或/etc/profile文件來配置unix環(huán)境變量
3.安裝Go
默認操作系統(tǒng)為Ubuntu。
1)安裝 C 工具
Go 的工具鏈是用 C 語言編寫的病往,因此在安裝 Go 之前你需要先安裝相關的 C 工具捣染。
sudo apt-get install bison ed gawk gcc libc6-dev make
2)安裝golang
如果要從舊版本的Go升級姊氓,則必須先刪除現(xiàn)有版本芝加。
-
apt-get安裝
sudo apt-get install golang go version #查看版本
-
下載二進制文件安裝
從 官方頁面 下載 Go 的二進制軟件到計算機上
wget https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz tar -zxvf go1.13.4.linux-amd64.tar.gz -C $GOROOT # 修改/etc/profile
export PATH=GOROOT/bin
- 獲取 Go 源代碼編譯安裝
如果二進制分行版不適用于當前操作系統(tǒng)和體系結構的組合,可以從 [官方頁面](https://golang.org/dl/) 下載 Go 的源碼包到計算機上堪滨,然后將解壓后的目錄 `go` 通過命令移動到 `$GOROOT` 所指向的位置畔勤。
```shell
wget https://dl.google.com/go/go1.13.4.src.tar.gz
tar -zxvf go1.13.4.src.tar.gz
sudo mv go $GOROOT
```
編譯源代碼
```shell
cd $GOROOT/src
./all.bash # 包含安裝測試
# 或
./make.bash # 僅構建
```
Go 安裝目錄(`$GOROOT`)的文件夾結構:
- `/bin`:包含可執(zhí)行文件蕾各,如:編譯器,Go 工具
- `/doc`:包含示例程序硼被,代碼工具示损,本地文檔等
- `/lib`:包含文檔模版
- `/misc`:包含與支持 Go 編輯器有關的配置文件以及 cgo 的示例
- `/os_arch`:包含標準庫的包的對象文件(`.a`)
- `/src`:包含源代碼構建腳本和標準庫的包的完整源代碼(Go 是一門開源語言)
- `/src/cmd`:包含 Go 和 C 的編譯器和命令行腳本
- 安裝測試
在Go 的工作目錄$GOPATH創(chuàng)建工作空間(`src`、`pkg` 和 `bin`)嚷硫,在src/hello目錄下創(chuàng)建hello.go检访。
```go
package main
import "fmt"
func main() {
fmt.Printf("hello, world\n")
}
編譯hello.go
cd $GOPATH/src/hello/
go build
4.Go runtime 虛擬機
? 盡管 Go 編譯器產生的是本地可執(zhí)行代碼,這些代碼仍舊運行在 Go 的 runtime當中(在目錄 $GOROOT/src/runtime中找到相關內容)仔掸。
? 這個 runtime 類似 Java 和 .NET 語言所用到的虛擬機脆贵,它負責管理包括內存分配、垃圾回收起暮、棧處理卖氨、goroutine、channel、切片(slice)筒捺、map 和反射(reflection)等等柏腻。
? Go 的可執(zhí)行文件都比相對應的源代碼文件要大很多,這說明了 Go 的 runtime 嵌入到了每一個可執(zhí)行文件當中系吭。Go 不需要依賴任何其它文件五嫂,它只需要一個單獨的靜態(tài)文件。
1)垃圾回收器
Go 擁有簡單卻高效的標記-清除回收器肯尺。它的主要思想來源于 IBM 的可復用垃圾回收器沃缘,旨在打造一個高效、低延遲的并發(fā)回收器则吟。
目前 gccgo 編譯器還沒有回收器槐臀。
2)Goroutine 并行設計
Goroutine能夠讓程序以異步的方式運行,不需要擔心一個函數導致程序中斷氓仲,因此Go也非常適合網絡服務水慨。
Goroutine是類似線程的概念(但Goroutine并不是線程)。
- 線程屬于系統(tǒng)層面寨昙,通常來說創(chuàng)建一個新的線程會消耗較多的資源且管理不易讥巡。
- Goroutine就像輕量級的線程掀亩,但我們稱其為并發(fā)舔哪,一個Go程序可以運行超過數萬個 Goroutine,并且這些性能都是原生級的槽棍,隨時都能夠關閉捉蚤、結束。
- 一個核心里面可以有多個Goroutine炼七,透過GOMAXPROCS參數能夠限制Gorotuine可以占用幾個系統(tǒng)線程來避免失控缆巧。
程序并行示例
// 程序順序執(zhí)行
func main() {
// 假設 loop 是一個會重複執(zhí)行十次的迴圈函式。
// 迴圈執(zhí)行完畢才會往下執(zhí)行豌拙。
loop()
// 執(zhí)行另一個迴圈陕悬。
loop()
}
// 程序并行執(zhí)行
func main() {
// 透過 `go`,我們可以把這個函式同步執(zhí)行按傅,
// 如此一來這個函式就不會阻塞主程式的執(zhí)行捉超。
go loop()
// 執(zhí)行另一個迴圈。
loop()
}
Go讓其中一個函數同步運行唯绍,如此就不需要等待該函數運行完后才能運行下一個函數拼岳。
5.Go 解析器【了解】
類似于python解析器,可以讓go程序像腳本語言一樣逐行編譯和執(zhí)行况芒。
6. IDE
1)LiteIDE
LiteIDE 是一款非常好用的輕量級 Go 集成開發(fā)環(huán)境(基于 QT惜纸、Kate 和 SciTE),包含了跨平臺開發(fā)及其它必要的特性,對代碼編寫耐版、自動補全和運行調試都有極佳的支持祠够。它采用了 Go 項目的概念來對項目文件進行瀏覽和管理,它還支持在各個 Go 開發(fā)環(huán)境之間隨意切換以及交叉編譯的功能粪牲。
同時哪审,它具備了抽象語法樹視圖的功能,可以清楚地縱覽項目中的常量虑瀑、變量湿滓、函數、不同類型以及他們的屬性和方法舌狗。
可以從 GitHub 頁面獲取詳情叽奥。
2)GoClipse
其依附于著名的 Eclipse 這個大型開發(fā)環(huán)境,雖然需要安裝 JVM 運行環(huán)境痛侍,但卻可以很容易地享有 Eclipse 本身所具有的諸多功能朝氓。這是一個非常好的編輯器,完善的代碼補全主届、抽象語法樹視圖赵哲、項目管理和程序調試功能。
可以從 GitHub 頁面獲取詳情君丁。
7.格式化工具
go fmt
(gofmt
)這個工具可以將源代碼格式化成符合官方統(tǒng)一標準的風格枫夺,屬于語法風格層面上的小型重構。遵循統(tǒng)一的代碼風格是 Go 開發(fā)中無可撼動的鐵律绘闷,因此你必須在編譯或提交版本管理系統(tǒng)之前使用 gofmt
來格式化你的代碼橡庞。
# 格式化源文件的代碼
gofmt –w program.go
# 不加參數 -w 則只會打印格式化后的結果而不重寫文件
# 格式化并重寫所有 Go 源文件
gofmt -w *.go
# 會格式化并重寫 map1 目錄及其子目錄下的所有 Go 源文件
gofmt map1
8.代碼文檔生成器
go doc
工具會從 Go 程序和包文件中提取頂級聲明的首行注釋以及每個對象的相關注釋,并生成相關文檔印蔗。
go doc package # 獲取包的文檔注釋扒最,例如:go doc fmt 會顯示使用 godoc 生成的 fmt 包的文檔注釋。
go doc package/subpackage # 獲取子包的文檔注釋华嘹,例如:go doc container/list吧趣。
go doc package function # 獲取某個函數在某個包中的文檔注釋,例如:go doc fmt Printf 會顯示有關 fmt.Printf() 的使用說明耙厚。
這個工具只能獲取在 Go 安裝目錄下 ../go/src
中的注釋內容强挫。
它還可以作為一個本地文檔瀏覽 web 服務器。在命令行輸入 godoc -http=:6060
颜曾,然后使用瀏覽器打開 http://localhost:6060 后纠拔,就可以看到本地文檔瀏覽服務器提供的頁面。
9.其他工具
-
go install
是安裝 Go 包的工具泛豪。主要用于安裝非標準庫的包文件稠诲,將源代碼編譯成對象文件侦鹏。- go build :用于編譯包,生成可執(zhí)行文件臀叙,必須有main包才可以(package main)略水。
- go install :主要用來生成庫和工具
- (如果有main包)編譯后生成的可執(zhí)行工具文件放到 bin 目錄($GOPATH/bin);
- 編譯后的庫文件放到 pkg 目錄下($GOPATH/pkg)
- go run :編譯并直接運行程序劝萤,它會產生一個臨時文件(但不會生成 .exe 文件)渊涝,直接在命令行輸出程序執(zhí)行結果,方便用戶調試床嫌。
-
go fix
用于將你的 Go 代碼從舊的發(fā)行版遷移到最新的發(fā)行版跨释,它主要負責簡單的、重復的厌处、枯燥無味的修改工作鳖谈,如果像 API 等復雜的函數修改,工具則會給出文件名和代碼行數的提示以便讓開發(fā)人員快速定位并升級代碼阔涉。go fix
之所以能夠正常工作是因為 Go 在標準庫就提供生成抽象語法樹和通過抽象語法樹對代碼進行還原的功能缆娃。該工具會嘗試更新當前目錄下的所有 Go 源文件,并在完成代碼更新后在控制臺輸出相關的文件名稱瑰排。 -
go test
是一個輕量級的單元測試框架贯要。
四、首個Go程序和庫
1.第一個Go程序
-
在工作區(qū)$GOPATH創(chuàng)建相應的包目錄
mkdir $GOPATH/src/github.com/user/hello
-
新建hello.go文件
package main //必須包含main包 import "fmt" func main() { fmt.Println("Hello, World") }
-
用go 工具編譯與安裝程序
go install github.com/user/hello # 可以在任意路徑下執(zhí)行椭住,會根據環(huán)境變量$GOPATH檢索 # 如果在包的路徑下崇渗,可以直接install cd $GOPATH/src/github.com/user/hello go install
-
運行程序
$ $GOPATH/bin/hello Hello, world.
注意:可以將第3、第4步簡化為go run github.com/user/hello
2.第一個Go Library
參考:Golang標準庫
-
在工作區(qū)$GOPATH創(chuàng)建相應的包目錄
mkdir $GOPATH/src/github.com/user/stringutil
-
新建
reverse.go
文件無需包含main包
// Package stringutil contains utility functions for working with strings. package stringutil // Reverse returns its argument string reversed rune-wise left to right. func Reverse(s string) string { r := []rune(s) for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] } return string(r) }
-
測試Go庫
cd $GOPATH/src/github.com/user/stringutil go build
-
修改上述的hello.go文件函荣,調用Go庫
package main import ( "fmt" "github.com/user/stringutil" //導入庫 ) func main() { fmt.Println(stringutil.Reverse("!oG ,olleH")) }
-
編譯安裝運行hello.go
go install github.com/user/hello $GOPATH/bin/hello