了解套件

已完成

Go 中的套件類似於其他程式設計語言的程式庫或模組。 您可以封裝程式碼,並在他處加以重複使用。 套件的原始程式碼可在多個 .go 檔案中散發。 到目前為止,我們已撰寫 main 套件,並對其他原生套件進行了一些參考。

在本節中,您將了解是什麼套件。 您也將了解如何建立套件,以及如何使用外部套件。

主要套件

您可能已注意到,即使是 Go 中最直接的程式,也必須是套件的一部分。 預設套件通常是 main,也就是我們目前使用的套件。 如果程式是 main 套件的一部分,Go 就會產生二進位檔案。 該檔案執行時,會呼叫 main() 函式。

換句話說,當您使用 main 套件時,程式將會產生獨立的可執行檔。 不過,若程式所屬的套件並非 main,Go 就不會產生二進位檔案。 這時會產生套件封存檔 (副檔名為 .a 的檔案)。

在 Go 中,封裝名稱會遵循慣例。 套件會使用匯入路徑的最後一部分作為名稱。 例如,Go 標準程式庫含有名為 math/cmplx 的套件,可提供實用的程式碼來處理複數。 此套件的匯入路徑是 math/cmplx,您要將之匯入,如下所示:

import "math/cmplx"

若要參考封裝中的物件,可使用封裝名稱 cmplx,如下所示:

cmplx.Inf()

我們來建立套件吧。

建立套件

$GOPATH/src 目錄中建立名為 calculator 的新目錄。 建立名為 sum.go 的檔案。 樹狀目錄看起來應該會類似此目錄:

src/
  calculator/
    sum.go

使用套件的名稱來初始化 sum.go 檔案:

package calculator

您現在可以開始撰寫套件的函式和變數。 與其他程式設計語言不同的是,Go 不會提供 publicprivate 關鍵字來指出是否可以從套件外部或內部呼叫變數或函式。 但是 Go 會遵循兩個簡單的規則:

  • 如果您想要將某項目設為私用,請使用小寫字母來作為其名稱的開頭。
  • 如果您想要將某項目設為公用,請使用大寫字母來作為其名稱的開頭。

讓我們將下列程式碼新增至我們所建立的計算機套件:

package calculator

var logMessage = "[LOG]"

// Version of the calculator
var Version = "1.0"

func internalSum(number int) int {
    return number - 1
}

// Sum two integer numbers
func Sum(number1, number2 int) int {
    return number1 + number2
}

我們來看看該程式碼中的一些項目:

  • logMessage 變數只能從套件內呼叫。
  • 您可以從任何位置連線到 Version 變數。 建議您加入註解來描述此變數的用途。 (對使用套件的每個人來說,此描述相當實用。)
  • internalSum 函式只能從套件內呼叫。
  • 您可以從任何位置連線到 Sum 函式。 建議您加入註解來描述此函式的用途。

若要確認一切是否正常運作,您可以在 calculator 目錄中執行 go build 命令。 請注意,這麼做不會產生可執行的二進位檔。

建立模組

您已將計算機功能放置在套件內。 現在可以將套件放入模組中。 Go 模組通常包含提供相關功能的套件。 套件的模組也會指定內容,讓 Go 必須執行您已群組在一起的程式碼。 此內容相關資訊包括您為其撰寫程式碼的 Go 版本。

此外,模組還可協助其他開發人員參考程式碼的特定版本,讓您更輕鬆地使用相依性。 另一個優點是我們程式的原始程式碼不一定要存在於 $GOPATH/src 目錄中。 解除這項限制可讓您更方便地在其他專案中同時使用不同套件版本。

因此,若要建立 calculator 套件的模組,請在根目錄 ($GOPATH/src/calculator) 中執行此命令:

go mod init github.com/myuser/calculator

在您執行此命令之後,github.com/myuser/calculator 會成為模組的名稱。 您將會在其他程式中使用該名稱來進行參考。 此命令也會建立名為 go.mod 的新檔案。 最後,樹狀目錄現在看起來像此目錄:

src/
  calculator/
    go.mod
    sum.go

go.mod 檔案的內容應該如下列程式碼所示。 (Go 版本可能不同。)

module github.com/myuser/calculator

go 1.14

若要在其他程式中參考您的 calculator 套件,必須使用模組名稱將之匯入。 在此案例中,該名稱為 github.com/myuser/calculator。 現在讓我們來看看如何使用此套件的範例。

注意

在過去,管理 Go 中的相依性並不容易。 相依性管理系統仍是一項進行中的工作。 如果您想要深入了解模組,請參閱 Go 部落格中發佈的這一系列貼文

參考本機套件 (模組)

現在讓我們來使用套件。 我們將繼續使用仍在使用中的範例應用程式。 這次,main 套件中沒有 sum 函式,我們要使用稍早在 calculator 套件中建立的函式。

樹狀檔案結構現在應該看起來像這樣:

src/
  calculator/
    go.mod
    sum.go
  helloworld/
    main.go

我們會將此程式碼用於 $GOPATH/src/helloworld/main.go 檔案:

package main

import (
  "fmt"
  "github.com/myuser/calculator"
)

func main() {
    total := calculator.Sum(3, 5)
    fmt.Println(total)
    fmt.Println("Version: ", calculator.Version)
}

請注意,匯入陳述式會使用您建立的套件名稱:calculator。 若要從該套件呼叫 Sum 函式,則必須包含該套件名稱,如 calculator.Sum 中所示。 最後,您現在也可以存取 Version 變數了。 您可以透過此形式呼叫該變數:calculator.Version

如果您嘗試現在執行程式,其將無法運作。 您必須讓 Go 知道您將使用模組來參考其他套件。 若要這樣做,請在 $GOPATH/src/helloworld 目錄中執行此命令:

go mod init helloworld

在上一個命令中,helloworld 是專案的名稱。 此命令會建立新的 go.mod 檔案,因此樹狀目錄現在看起來會像這樣:

src/
  calculator/
    go.mod
    sum.go
  helloworld/
    go.mod
    main.go

如果您開啟 go.mod 檔案,應該會看到如下列程式碼所示的內容。 (Go 版本可能不同。)

module helloworld

go 1.14

由於您參考的是模組的本機複本,所以您需要讓 Go 知道您不想要使用遠端位置。 因此,您需要手動修改 go.mod 檔案以包含參考,如下所示:

module helloworld

go 1.14

require github.com/myuser/calculator v0.0.0

replace github.com/myuser/calculator => ../calculator

replace 關鍵字會指定使用本機目錄,而不是模組的遠端位置。 在此案例中,因為 helloworldcalculator 程式位於 $GOPATH/src 中,所以位置是 ../calculator。 如果模組的來源位於不同的位置,您可以在此定義本機路徑。

使用此命令來執行程式:

go run main.go

輸出應如下所示:

8
Version:  1.0

挑戰 1

如果您嘗試從主應用程式中的 calculator 套件呼叫 logMessage 變數或 internalSum 函式,會發生什麼事? 其是否會執行? 試用一下!

問題解決方案

package main

import (
 "fmt"
 "github.com/myuser/calculator"
)

func main() {
    total := calculator.internalSum(5)
    fmt.Println(total)
    fmt.Println("Version: ", calculator.logMessage)
}

發佈套件

發佈 Go 套件相當簡單。 您只需要讓套件原始程式碼可供公開使用即可。 大部分的開發人員都會使用 GitHub 讓套件可供大眾使用,這就是為什麼您有時會在 import 語句中找到 github.com 的參考。

例如,如果您想要將 calculator 套件發行至您的 GitHub 帳戶,您必須建立名為 calculator 的存放庫。 URL 看起來應該會像這樣:

https://github.com/myuser/calculator

您將會透過標記存放庫來為套件建立版本,如下所示:

git tag v0.1.0
git push origin v0.1.0

想要使用您套件的開發人員 (包括您) 都會透過下列方式來參考該套件:

import "github.com/myuser/calculator"

讓我們更詳細地討論如何參考第三方套件。

參考外部 (協力廠商) 套件

有時候您的程式必須參考其他開發人員所撰寫的套件。 這些套件通常可在 GitHub 上取得。 無論您正在開發套件 (main 以外的套件),或是獨立程式 (main 套件),皆適用下列參考第三方套件的指示。

讓我們來新增 rsc.io/quote 套件的參考:

package main

import (
    "fmt"
    "github.com/myuser/calculator"
    "rsc.io/quote"
)

func main() {
    total := calculator.Sum(3, 5)
    fmt.Println(total)
    fmt.Println("Version: ", calculator.Version)
    fmt.Println(quote.Hello())
}

如果您使用 Visual Studio Code,go.mod 檔案會在您儲存檔案時更新。 現在的樣貌如下:

module helloworld

go 1.14

require (
    github.com/myuser/calculator v0.0.0
    rsc.io/quote v1.5.2
)

replace github.com/myuser/calculator => ../calculator

請注意 rsc.io/quote 如何參考特定版本的套件。 當您需要升級程式的相依性時,您必須在此變更版本。

使用下列命令再次執行程式:

go run main.go

輸出應該看起來像這樣:

8
Version:  1.0
Hello, world.

未來所有第三方套件的參考都必須位在 go.mod 檔案中。 當您執行或編譯應用程式時,Go 會下載其所有相依性。