Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

3.1 Golang 介紹與環境安裝

專案地址:https://github.com/EDDYCJY/go-gin-example

本文目標

  • 學會安裝 Go。
  • 知道什麼是 Go。
  • 知道什麼是 Go modules。
  • 瞭解 Go modules 的小歷史。
  • 學會簡單的使用 Go modules。
  • 瞭解 Gin,並簡單跑起一個 Demo。

準備環節

安裝 Go

Centos

首先,根據對應的作業系統選擇安裝包 下載,在這裡我使用的是Centos 64位系統,如下:

$ wget https://studygolang.com/dl/golang/go1.13.1.linux-amd64.tar.gz

$ tar -zxvf go1.13.1.linux-amd64.tar.gz

$ mv go/ /usr/local/

設定 /etc/profile

vi /etc/profile

新增環境變數GOROOT和將GOBIN新增到PATH中

export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin

設定完畢後,執行命令令其生效

source /etc/profile

在控制檯輸入go version,若輸出版本號則安裝成功,如下:

$ go version
go version go1.13.1 linux/amd64

MacOS

在 MacOS 上安裝 Go 最方便的辦法就是使用 brew,安裝如下:

$ brew install go

升級命令如下:

$ brew upgrade go

注:升級命令你不需要執行,但我想未來你有一天會用到的。

同樣在控制檯輸入go version,若輸出版本號則安裝成功

瞭解 Go

是什麼

Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.

上述為官方說明,如果簡單來講,大致為如下幾點:

  • Go 是程式語言。
  • 谷歌爸爸撐腰。
  • 語言級高併發。
  • 上手快,入門簡單。
  • 簡潔,很有特色。
  • 國內使用人群逐年增多。

誰在用

image

有什麼

那麼大家會有些疑問,糾結 Go 本身有什麼東西,我們剛剛設定的環境變數又有什麼用呢,甚至作為一名老粉,你會糾結 GOPATH 去哪裡了,我們一起接著往下看。

目錄結構

首先,我們在解壓的時候會得到一個名為 go 的資料夾,其中包括了所有 Go 語言相關的一些檔案,如下:

$ tree -L 1 go
go
├── api
├── bin
├── doc
├── lib
├── misc
├── pkg
├── src
├── test
└── ...

在這之中包含了很多資料夾和檔案,我們來簡單說明其中主要資料夾的作用:

  • api:用於存放依照 Go 版本順序的API增量列表檔案。這裡所說的API包含公開的變數、常量、函式等。這些API增量列表檔案用於 Go 語言API檢查
  • bin:用於存放主要的標準命令檔案(可執行檔案),包含gogodocgofmt
  • blog:用於存放官方部落格中的所有文章
  • doc:用於存放標準庫的HTML格式的程式文件。我們可以透過godoc命令啟動一個Web程式展示這些文件
  • lib:用於存放一些特殊的庫檔案
  • misc:用於存放一些輔助類的說明和工具
  • pkg:用於存放安裝Go標準庫後的所有歸檔檔案(以.a結尾的檔案)。注意,你會發現其中有名稱為linux_amd64的資料夾,我們稱為平臺相關目錄。這類資料夾的名稱由對應的作業系統和計算架構的名稱組合而成。透過go install命令,Go程式會被編譯成平臺相關的歸檔檔案存放到其中
  • src:用於存放 Go自身、Go 標準工具以及標準庫的所有原始碼檔案
  • test:存放用來測試和驗證Go本身的所有相關檔案

環境變數

你可能會疑惑剛剛設定的環境變數是什麼,如下:

  • GOROOT:Go的根目錄。
  • PATH 下增加 $GOROOT/binGobin下會存放可執行檔案,我們把他加入 $PATH 後,未來拉下來並編譯後的二進位制檔案就可以直接在命令列使用。

那在什麼東西都不下載的情況下,$GOBIN 下面有什麼呢,如下:

bin/ $ls
go  gofmt
  • go:Go 二進位制本身。
  • gofmt:程式碼格式化工具。

因此我們剛剛把 $GOBIN 加入到 $PATH 後,你執行 go version 命令後就可以檢視到對應的輸出結果。

注:MacOS 用 brew 安裝的話就不需要。

放在哪

你現在知道 Go 是什麼了,也知道 Go 的原始碼擺在哪了,你肯定會想,那我應用程式碼放哪呢,答案是在 Go1.11+ 和開啟 Go Modules 的情況下襬哪都行

瞭解 Go Modules

瞭解歷史

在過去,Go 的依賴包管理在工具上混亂且不統一,有 dep,有 glide,有 govendor...甚至還有因為外網的問題,頻頻導致拉不下來包,很多人苦不堪言,盼著官方給出一個大一統做出表率。

而在 Go modules 正式出來之前還有一個叫 dep 的專案,我們在上面有提到,它是 Go 的一個官方實驗性專案,目的也是為了解決 Go 在依賴管理方面的問題,當時社群裡面幾乎所有的人都認為 dep 肯定就是未來 Go 官方的依賴管理解決方案了。

但是萬萬沒想到,半路殺出個程咬金,Russ Cox 義無反顧地推出了 Go modules,這瞬間導致一石激起千層浪,讓社群炸了鍋。大家一致認為 Go team 實在是太霸道、太獨裁了,連個招呼都不打一聲。我記得當時有很多人在網上跟 Russ Cox 口水戰,各種依賴管理解決方案的專家都冒出來發表意見,討論範圍甚至一度超出了 Go 語言的圈子觸及到了其他語言的領域。

當然,最後,推成功了,Go modules 已經進入官方工具鏈中,與 Go 深深結合,以前常說的 GOPATH 終將會失去它原有的作用,而且它還提供了 GOPROXY 間接解決了國內訪問外網的問題。

瞭解 Russ Cox

在上文中提到的 Russ Cox 是誰呢,他是 Go 這個專案目前程式碼提交量最多的人,甚至是第二名的兩倍還要多(從 2019年 09 月 30 日前來看)。

Russ Cox 還是 Go 現在的掌舵人(大家應該知道之前 Go 的掌舵人是 Rob Pike,但是聽說由於他本人不喜歡特朗普執政所以離開了美國,然後他歲數也挺大的了,所以也正在逐漸交權,不過現在還是在參與 Go 的發展)。

Russ Cox 的個人能力相當強,看問題的角度也很獨特,這也就是為什麼他剛一提出 Go modules 的概念就能引起那麼大範圍的響應。雖然是被強推的,但事實也證明當下的 Go modules 表現得確實很優秀,所以這表明一定程度上的 “獨裁” 還是可以接受的,至少可以保證一個專案能更加專一地朝著一個方向發展。

初始化行為

在前面我們已經瞭解到 Go 依賴包管理的歷史情況,接下來我們將正式的進入使用,首先你需要有一個你喜歡的目錄,例如:$ mkdir ~/go-application && cd ~/go-application,然後執行如下命令:

$ mkdir go-gin-example && cd go-gin-example

$ go env -w GO111MODULE=on

$ go env -w GOPROXY=https://goproxy.cn,direct

$ go mod init github.com/EDDYCJY/go-gin-example
go: creating new go.mod: module github.com/EDDYCJY/go-gin-example

$ ls
go.mod
  • mkdir xxx && cd xxx:建立並切換到專案目錄裡去。
  • go env -w GO111MODULE=on:開啟 Go modules 開關(目前在 Go1.13 中預設值為 auto)。
  • go env -w GOPROXY=...:設定 GOPROXY 代理,這裡主要涉及到兩個值,第一個是 https://goproxy.cn,它是由七牛雲背書的一個強大穩定的 Go 模組代理,可以有效地解決你的外網問題;第二個是 direct,它是一個特殊的 fallback 選項,它的作用是用於指示 Go 在拉取模組時遇到錯誤會回源到模組版本的源地址去抓取(比如 GitHub 等)。
  • go mod init [MODULE_PATH]:初始化 Go modules,它將會生成 go.mod 檔案,需要注意的是 MODULE_PATH 填寫的是模組引入路徑,你可以根據自己的情況修改路徑。

在執行了上述步驟後,初始化工作已完成,我們開啟 go.mod 檔案看看,如下:

module github.com/EDDYCJY/go-gin-example

go 1.13

預設的 go.mod 檔案裡主要是兩塊內容,一個是當前的模組路徑和預期的 Go 語言版本。

基礎使用

  • go get 拉取新的依賴
    • 拉取最新的版本(優先擇取 tag):go get golang.org/x/text@latest
    • 拉取 master 分支的最新 commit:go get golang.org/x/text@master
    • 拉取 tag 為 v0.3.2 的 commit:go get golang.org/x/text@v0.3.2
    • 拉取 hash 為 342b231 的 commit,最終會被轉換為 v0.3.2:go get golang.org/x/text@342b2e
    • go get -u 更新現有的依賴
    • go mod download 下載 go.mod 檔案中指明的所有依賴
    • go mod tidy 整理現有的依賴
    • go mod graph 檢視現有的依賴結構
    • go mod init 生成 go.mod 檔案 (Go 1.13 中唯一一個可以生成 go.mod 檔案的子命令)
  • go mod edit 編輯 go.mod 檔案
  • go mod vendor 匯出現有的所有依賴 (事實上 Go modules 正在淡化 Vendor 的概念)
  • go mod verify 校驗一個模組是否被篡改過

這一小節主要是針對 Go modules 的基礎使用講解,還沒具體的使用,是希望你能夠留個印象,因為在後面章節會不斷夾雜 Go modules 的知識點。

注:建議閱讀官方文件 wiki/Modules

開始 Gin 之旅

是什麼

Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.

Gin是用 Go 開發的一個微框架,類似 Martinier 的API,重點是小巧、易用、效能好很多,也因為 httprouter 的效能提高了40倍。

安裝

我們回到剛剛建立的 go-gin-example 目錄下,在命令列下執行如下命令:

$ go get -u github.com/gin-gonic/gin
go: downloading golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223
go: extracting golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223
go: finding github.com/gin-contrib/sse v0.1.0
go: finding github.com/ugorji/go v1.1.7
go: finding gopkg.in/yaml.v2 v2.2.3
go: finding golang.org/x/sys latest
go: finding github.com/mattn/go-isatty v0.0.9
go: finding github.com/modern-go/concurrent latest
...

go.sum

這時候你再檢查一下該目錄下,會發現多個了個 go.sum 檔案,如下:

github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW...
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW...
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g=
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2...
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO...
...

go.sum 檔案詳細羅列了當前專案直接或間接依賴的所有模組版本,並寫明瞭那些模組版本的 SHA-256 雜湊值以備 Go 在今後的操作中保證專案所依賴的那些模組版本不會被篡改。

go.mod

既然我們下載了依賴包,go.mod 檔案會不會有所改變呢,我們再去看看,如下:

module github.com/EDDYCJY/go-gin-example

go 1.13

require (
        github.com/gin-contrib/sse v0.1.0 // indirect
        github.com/gin-gonic/gin v1.4.0 // indirect
        github.com/golang/protobuf v1.3.2 // indirect
        github.com/json-iterator/go v1.1.7 // indirect
        github.com/mattn/go-isatty v0.0.9 // indirect
        github.com/ugorji/go v1.1.7 // indirect
        golang.org/x/sys v0.0.0-20190927073244-c990c680b611 // indirect
        gopkg.in/yaml.v2 v2.2.3 // indirect
)

確確實實發生了改變,那多出來的東西又是什麼呢,go.mod 檔案又儲存了什麼資訊呢,實際上 go.mod 檔案是啟用了 Go modules 的專案所必須的最重要的檔案,因為它描述了當前專案(也就是當前模組)的元資訊,每一行都以一個動詞開頭,目前有以下 5 個動詞:

  • module:用於定義當前專案的模組路徑。
  • go:用於設定預期的 Go 版本。
  • require:用於設定一個特定的模組版本。
  • exclude:用於從使用中排除一個特定的模組版本。
  • replace:用於將一個模組版本替換為另外一個模組版本。

你可能還會疑惑 indirect 是什麼東西,indirect 的意思是傳遞依賴,也就是非直接依賴。

測試

編寫一個test.go檔案

package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // listen and serve on 0.0.0.0:8080
}

執行test.go

$ go run test.go 
...
[GIN-debug] GET    /ping                     --> main.main.func1 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080

訪問 $HOST:8080/ping,若返回{"message":"pong"}則正確

curl 127.0.0.1:8080/ping

至此,我們的環境安裝和初步執行都基本完成了。

再想一想

剛剛在執行了命令 $ go get -u github.com/gin-gonic/gin 後,我們查看了 go.mod 檔案,如下:

...
require (
        github.com/gin-contrib/sse v0.1.0 // indirect
        github.com/gin-gonic/gin v1.4.0 // indirect
        ...
)

你會發現 go.mod 裡的 github.com/gin-gonic/ginindirect 模式,這顯然不對啊,因為我們的應用程式已經實際的編寫了 gin server 程式碼了,我就想把它調對,怎麼辦呢,在應用根目錄下執行如下命令:

$ go mod tidy

該命令主要的作用是整理現有的依賴,非常的常用,執行後 go.mod 檔案內容為:

...
require (
        github.com/gin-contrib/sse v0.1.0 // indirect
        github.com/gin-gonic/gin v1.4.0
        ...
)

可以看到 github.com/gin-gonic/gin 已經變成了直接依賴,調整完畢。

參考

本系列示例程式碼

相關文件

關於

修改記錄

  • 第一版:2018年02月16日釋出文章
  • 第二版:2019年10月01日修改文章

如果有任何疑問或錯誤,歡迎在 issues 進行提問或給予修正意見,如果喜歡或對你有所幫助,歡迎 Star,對作者是一種鼓勵和推進。

我的微信公眾號

image