簡介

GO 語言是谷歌在2009年發布的第二款開源編程語言。它專門針對多處理器系統應用程序的編程進行了優化,使用Go編譯的程序可以媲美C或C++代碼的速度,而且更加安全、支持並行執行。

Go 的目標是希望提升現有編程語言對程序庫的依賴性(dependency)的管理,這些軟體元素會被應用程序反覆調用。由於支持並行編程模式,因此這一語言也被設計用來解決需要多處理器完成的任務。

特點

  1. 簡潔 快速 安全
  2. 並行 有趣 開源,
  3. 內存管理,數組安全,編譯迅速

Go 適合用來做什麼

  1. 伺服器編程,以前你如果使用 C 或者 C++ 做的那些事情,用 Go 來做很合適,例如處理日誌、數據打包、虛擬機處理、文件系統等。
  2. 分散式系統,資料庫代理器等。
  3. 網路編程,這一塊目前應用最廣,包括 Web 應用、API 應用。
  4. 雲平台,目前國外很多雲平台在採用 Go 開發。

如何編寫 Go 代碼

編寫 Go 代碼前,首先有一個概覽:

  1. Go 程序員通常將他們所有的 Go 代碼保存在一個工作區中。
  2. 工作區包含許多版本控制存儲庫 (例如,由 Git 管理)。
  3. 每個存儲庫都包含一個或多個包。
  4. 每個軟體包由一個目錄中的一個或多個 Go 源文件組成。
  5. 包的目錄的路徑決定了它的導入路徑。

但注意,這與其他編程環境不同,在這些編程環境中,每個項目都有一個單獨的工作區,工作區與版本控制存儲庫緊密相關。

關於 Go 的工作區:

工作區是一個目錄層次結構,其根目錄包含三個目錄:

  1. src 包含 Go 源文件,
  2. pkg 包含包對象
  3. bin 包含可執行命令。

該 go 工具構建源包並將生成的二進位文件安裝到 pkg 和 bin 目錄。

該 src 子目錄通常包含多個版本控制存儲庫(例如 Git 或 Mercurial),用於跟蹤一個或多個源包的開發。

導入路徑:

一個導入路徑是唯一標識一個包的字元串。程序包的導入路徑對應於其在工作區內或遠程存儲庫中的位置。來自標準庫的軟體包被賦予諸如"fmt"和的短導入路徑 "net/http"。對於你自己的軟體包,你必須選擇一個基本路徑,這個基本路徑不可能與未來添加到標準庫或其他外部庫中相衝突。

第一個 Go 程序:

要編譯並運行一個簡單的程序,首先選擇一個包路徑(我們將使用 github.com/user/hello)並在工作區內創建一個相應的包目錄:

$ mkdir $ GOPATH / src / github.com / user / hello

接下來,創建一個名為hello.go該目錄內的文件,其中包含以下Go代碼。

package main
import "fmt"
func main() {
    fmt.Printf("Hello, world.\n")
}

現在,您可以使用該go工具構建和安裝該程序:

$ go install github.com/user/hello

請注意,您可以從系統上的任何位置運行此命令。該 go工具通過查找github.com/user/hello指定的工作區內的程序包 來查找源代碼 GOPATH。

Go語音程序例子:

用Go寫成的「hello world」例子:

package main
import "fmt"
func main() {
         fmt.Println("Hello, World")
}

通過 Go 語言僅需幾行程序碼就完成 HTTP 網頁伺服器的實現:

package main
import (
    "io"
    "net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "Hello world!")
}
func main() {
    http.HandleFunc("/", hello)
    http.ListenAndServe(":8000", nil)
}

Go 語言的垃圾回收

Go 的垃圾回收在1.5版本之前是採用了標記-清理的方法,即先標記出需要清理的內存,然後清理掉。實際上,標記清除法是一種常見垃圾回收演算法。下面就介紹一下常見的垃圾回收演算法。

常見的垃圾回收(GC)演算法

引用計數法

在每個對象內加入一個整數值,這個對象被引用時加一,從被引用的狀態中解除時減一,然後清理掉引用計數為0的對象。

這種方法的缺陷在於無法處理循環引用,當對象A與B互相持有對方的引用時,無法回收它們。

 

標記清除法

顧名思義,這個方法分為標記和清除兩步。

標記:從程序的根節點開始,遞歸地遍歷所有的對象以確定所有還在使用的對象,然後標記他們

清除:沒被標記的就全部回收就好了

當然了這個演算法也會有應該缺陷,在發動時必須暫停整個程序,不然發動時一些對象的狀態如果被其他的代碼改變,就可能把這些對象中不該回收的回收掉。而且當對象很多時,會消耗很多時間,讓整個程序暫停的時間太長對用戶體驗會造成極其不好的影響。GO 語言1.5之前使用的是這個演算法。

 

三色標記法

這種方法是對標記清理法的一種改進,最大的好處就是不再需要暫停程序了。

  1. 首先建立三個集合:白,灰,黑,之後把所有的對象放入白集合中。
  2. 從根節點遍歷所有對象,不需要遞歸,遍歷到的對象放入灰集合
  3. 遍歷灰色集合,被灰集合引用的對象從白集合中移到灰集合中,直到灰集合中沒有任何對象
  4. 通過 write-barrier 檢測這個過程中對象的變化,有變化時重複上面幾步,當對象沒有變化時,把灰集合中的對象移入黑集合
  5. 回收白集合中的對象

這個演算法的缺陷就在於,如果程序中垃圾產生的速度大於清理的速度,就會讓垃圾無法被清理,這個演算法應用於 GO 1.5和 GO 1.6

 

分代收集法

這個方法也是對標記清理法的一種改進,因為絕大多數對象的生命周期都很短,所以按照它們的生命周期來分代,一般來說是分為三代的:第0代,第1代,第2代

原理如下:

  1. 新對象視為第0代
  2. 當內存用量超過一定程度時(通常很低),對第0代進行標記清理
  3. 沒被清理掉的第0代對象歸入第1代
  4. 當內存用量超過一定程度時(通常較高),對第1代進行標記清理
  5. 以此類推

因為新對象的數量比較少,所以收集時會很快,當內存消耗過大時才觸發1代和2代收集,目前在使用這種演算法的語言(平台)有 jvm , .NET