使用 Glide 管理 Go 套件


更新 @ 2019-12-13: 由 Go 1.13 開始,請使用內置的 Go Module 來管理套件。


Glide 是一個 Go 套件管理工具,就像 NodeJS 中的 npm 一樣。我們用以下一個例子來看看它是如何運作的。

在 $GOPATH 中創建項目

項目文件夾必須在 $GOPATH 下才能讓 Go 找到套件路徑。在此例子中項目的根文件夾在 $GOPATH/src/gitlab.com/ykyuen/glide-example

簡單的 Hello World Go 程式

我們來創建一個簡單的 Go 程式。

main.go

1
2
3
4
5
6
7
package main

import "fmt"

func main() {
  fmt.Println("hello world")
}

編譯並運行

1
2
3
[ykyuen@camus glide-example]$ go build -o hello
[ykyuen@camus glide-example]$ ./hello
hello world

添加一個 Go 套件

dustin/go-humanize 是一個實用的的 Go 套件用來格式化數字、字符串和時間。讓我們更新我們的 Go 程式。

main.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

import humanize "github.com/dustin/go-humanize"
import "fmt"

func main() {
  fmt.Println("hello world")
  fmt.Printf("That file is %s.\n", humanize.Bytes(82854982)) // That file is 83 MB.
  fmt.Printf("You're my %s best friend.\n", humanize.Ordinal(193)) // You are my 193rd best friend.
  fmt.Printf("You owe $%s.\n", humanize.Comma(6582491)) // You owe $6,582,491.
}

編譯的時候會出現以下錯誤。

1
2
3
4
[ykyuen@camus glide-example]$ go build -o hello
main.go8: cannot find package "github.com/dustin/go-humanize" in any of:
  /home/ykyuen/tools/go1.8.4/src/github.com/dustin/go-humanize (from $GOROOT)
  /home/ykyuen/go/src/github.com/dustin/go-humanize (from $GOPATH)

這是因為我們沒有下載 dustin/go-humanize。如果不使用 Glide,我們可以通過運行 go get 命令來解決。

1
go get github.com/dustin/go-humanize

但在這種情況下,任何 checkout 項目的人都不知道需要哪些套件才能夠編譯。如果您已經運行 go get 命令,請在繼續之前刪除已下載的套件。

使用 Glide

準備一個 glide.yaml

glide.yaml 可以透過 glide create 命令生成。它將掃描所有 .go 文件並架構所要的套件關係。以下是這個例子的輸出。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[ykyuen@camus glide-example]$ glide create
[INFO]  Generating a YAML configuration file and guessing the dependencies
[INFO]  Attempting to import from other package managers (use --skip-import to skip)
[INFO]  Scanning code to look for dependencies
[INFO]  --> Found reference to github.com/dustin/go-humanize
[INFO]  Writing configuration file (glide.yaml)
[INFO]  Would you like Glide to help you find ways to improve your glide.yaml configuration?
[INFO]  If you want to revisit this step you can use the config-wizard command at any time.
[INFO]  Yes (Y) or No (N)?
Y
[INFO]  Looking for dependencies to make suggestions on
[INFO]  --> Scanning for dependencies not using version ranges
[INFO]  --> Scanning for dependencies using commit ids
[INFO]  Gathering information on each dependency
[INFO]  --> This may take a moment. Especially on a codebase with many dependencies
[INFO]  --> Gathering release information for dependencies
[INFO]  --> Looking for dependency imports where versions are commit ids
[INFO]  No proposed changes found. Have a nice day.

glide.yaml

1
2
3
package: gitlab.com/ykyuen/glide-example
import:
- package: github.com/dustin/go-humanize

將 Go 套件下載到 vendor 文件夾

接下來,我們執行 glide install 命令來下載所需套件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[ykyuen@camus glide-example]$ glide install
[INFO]  Lock file (glide.lock) does not exist. Performing update.
[INFO]  Downloading dependencies. Please wait...
[INFO]  --> Fetching updates for github.com/dustin/go-humanize
[INFO]  Resolving imports
[INFO]  Downloading dependencies. Please wait...
[INFO]  Setting references for remaining imports
[INFO]  Exporting resolved dependencies...
[INFO]  --> Exporting github.com/dustin/go-humanize
[INFO]  Replacing existing vendor dependencies
[INFO]  Project relies on 1 dependencies.

這將會生成一個 glide.lock 文件和載有 dustin / go-humanize 套件的 vendor 文件夾。kglide.loc 文件裡記錄了套件的版本,它可以是一個 tag 或是一個 git commit hash

glide.lock

1
2
3
4
5
6
hash: de8aada0e0453f13dc438db5fb412db797d701d6afeadcc052c477fd55e01aa8
updated: 2017-12-04T2353.616704682+08:00
imports:
- name: github.com/dustin/go-humanize
  version: 8929fe90cee4b2cb9deb468b51fb34eba64d1bf0
testImports: []

更新套件版本

8929fe9 的版本的已經過時。我們可以在 glide.lock 文件中修改版本並再次執行 glide install 來下載新的套件。

glide.lock

1
2
3
4
5
6
hash: de8aada0e0453f13dc438db5fb412db797d701d6afeadcc052c477fd55e01aa8
updated: 2017-12-04T2353.616704682+08:00
imports:
- name: github.com/dustin/go-humanize
  version: bb3d318650d48840a39aa21a027c6630e198e626
testImports: []

1
2
3
4
5
6
7
8
[ykyuen@camus glide-example]$ glide install
[INFO]  Downloading dependencies. Please wait...
[INFO]  --> Found desired version locally github.com/dustin/go-humanize bb3d318650d48840a39aa21a027c6630e198e626!
[INFO]  Setting references.
[INFO]  --> Setting version for github.com/dustin/go-humanize to bb3d318650d48840a39aa21a027c6630e198e626.
[INFO]  Exporting resolved dependencies...
[INFO]  --> Exporting github.com/dustin/go-humanize
[INFO]  Replacing existing vendor dependencies

再一次編譯並運行

1
2
3
4
5
6
[ykyuen@camus glide-example]$ go build -o hello
[ykyuen@camus glide-example]$ ./hello
hello world
That file is 83 MB.
You're my 193rd best friend.
You owe $6,582,491.

要 Check in vendor 文件夾嗎?

對於 NodeJS 項目,我們通常會忽略代碼庫中的 node_modules 文件夾。另一方面,Go 社區有着不同的觀點。

現在還沒有一個絕對的答案,選擇你感覺更舒適的方案吧。

其它考慮

當項目越來越大時,隨著套件的關係越趨向複雜,Glide 下載所需的時間也會增加。此外,套件的版本也不易管理。

您或會想考慮使用另一個名為 dep 的套件管理工具,glide 的團隊建也建議使用 dep。請看看 dep 的項目狀態,然後選擇一個你認為更合適的工具。

總結

  • 項目必須在 $GOPATH 裡面。
  • Glide 會掃描所有的源代碼並會自動包含所需套件。
  • 套件的版本由 glide.lock 管理。
  • 應否 commit vendor 文件夾仍然沒有定案。
  • 下載時間隨套件的關係增加。
  • 完整的例子可以在此找到。