Golang 快速熟悉

一、簡介

Go(又稱Golang)是Google開發(fā)的一種靜態(tài)強類型硬鞍、編譯型并發(fā)型戴已,并具有垃圾回收功能編程語言固该。Go于2009年11月正式宣布推出,成為開放源代碼項目糖儡,支持Linux伐坏、macOSWindows等操作系統(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.與其他語言的比較

3.Go的缺失特性

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

二霉囚、Go項目風格

1.撰寫風格

Go 語言編碼規(guī)范

  • 每行程序結束后不需要撰寫分號(;)捕仔。
  • 大括號({)不能夠換行放置。
    • 換行會產生編譯錯誤
  • 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目锭、pkgbin评汰,這三個目錄分別用于存放源碼文件、包文件和可執(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=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 解析器【了解】

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 fmtgofmt)這個工具可以將源代碼格式化成符合官方統(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程序

參考:golang-examples

  • 在工作區(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
    
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末显押,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子傻挂,更是在濱河造成了極大的恐慌,老刑警劉巖挖息,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件金拒,死亡現(xiàn)場離奇詭異,居然都是意外死亡套腹,警方通過查閱死者的電腦和手機绪抛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來电禀,“玉大人幢码,你說我怎么就攤上這事〖夥桑” “怎么了症副?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵店雅,是天一觀的道長。 經常有香客問我贞铣,道長闹啦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任辕坝,我火速辦了婚禮窍奋,結果婚禮上,老公的妹妹穿的比我還像新娘酱畅。我一直安慰自己琳袄,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布纺酸。 她就那樣靜靜地躺著挚歧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吁峻。 梳的紋絲不亂的頭發(fā)上滑负,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音用含,去河邊找鬼矮慕。 笑死,一個胖子當著我的面吹牛啄骇,可吹牛的內容都是我干的痴鳄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缸夹,長吁一口氣:“原來是場噩夢啊……” “哼痪寻!你這毒婦竟也來了?” 一聲冷哼從身側響起虽惭,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤橡类,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后芽唇,有當地人在樹林里發(fā)現(xiàn)了一具尸體顾画,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年匆笤,在試婚紗的時候發(fā)現(xiàn)自己被綠了研侣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡炮捧,死狀恐怖庶诡,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情咆课,我是刑警寧澤末誓,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布扯俱,位于F島的核電站,受9級特大地震影響基显,放射性物質發(fā)生泄漏蘸吓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一撩幽、第九天 我趴在偏房一處隱蔽的房頂上張望库继。 院中可真熱鬧,春花似錦窜醉、人聲如沸宪萄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拜英。三九已至,卻和暖如春琅催,著一層夾襖步出監(jiān)牢的瞬間居凶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工藤抡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留侠碧,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓缠黍,卻偏偏與公主長得像弄兜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瓷式,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354