目录

package


package

Go 包与其他编程语言中的库或模块类似。 你可以打包代码,并在其他位置重复使用它。 包的源代码可以分布在多个 .go 文件中。

1 main 包

你可能注意到,在 Go 中,甚至最直接的程序都是包的一部分。 通常情况下,默认包是 main 包,即目前为止一直使用的包。 如果程序是 main 包的一部分,Go 会生成二进制文件。 运行该文件时,它将调用 main() 函数。

换句话说,当你使用 main 包时,程序将生成独立的可执行文件。 但当程序非是 main 包的一部分时,Go 不会生成二进制文件。 它生成包存档文件(具有 .a 扩展名的文件)。

在 Go 中,包名称需遵循约定。 包使用其导入路径的最后一部分作为名称。 例如,Go 标准库包含名为 math/cmplx 的包,该包提供用于处理复数的有用代码。 此包的导入路径为 math/cmplx,导入包的方式如下所示:

import "math/cmplx"

// 若要引用包中的对象,请使用包名称 cmplx,如下所示:
cmplx.Inf()

2 创建包

src/
  calculator/
    sum.go
// 用包的名称初始化 sum.go 文件:
package calculator

你现在可以开始编写包的函数和变量。 不同于其他编程语言,Go 不会提供 public 或 private 关键字,以指示是否可以从包的内外部调用变量或函数。 但 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
}
# 若要确认一切正常,可在 calculator 目录中运行 go build 命令。 如果执行此操作,请注意系统不会生成可执行的二进制文件。
go build

3 创建模块

你已将计算器功能放入包中。 现在可以将包放到模块中。 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


复制
module github.com/myuser/calculator

go 1.14

若要在其他程序中引用 calculator 包,需要使用模块名称进行导入。 在这种情况下,其名称为 github.com/myuser/calculator。 现在,让我们看一下示例,了解如何使用此包。

4 引用本地包(模块)

现在,让我们先使用包。 我们将继续使用我们一直使用的示例应用程序。 这一次,我们将使用之前在 calculator 包中创建的函数,而不是 main 包中的 sum 函数。

src/
  calculator/
    go.mod
    sum.go
  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)
}

请注意,import 语句使用所创建包的名称: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

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 关键字指定使用本地目录,而不是模块的远程位置。 在这种情况下,由于 helloworld 和 calculator 程序在 $GOPATH/src 中,因此位置只能是 ../calculator。 如果模块源位于不同的位置,请在此处定义本地路径。

5 引用外部(第三方)包

有时,程序需要引用其他开发人员编写的包。 你通常可以在 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())
}

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

日后对第三方包的所有引用都需要包含在 go.mod 文件中。 运行或编译应用程序时,Go 将下载其所有依赖项。