Golang 扩展包入门教程

Go

Go旨在鼓励良好的软件工程实践。高质量软件的指导原则之一是DRY原则-D on'not R epeat Yourself,这基本上意味着您永远不应编写相同的代码两次。您应该重用并尽可能建立在现有代码的基础上。

功能是允许代码重用的最基本的构建块。 软件包是代码可重用性的下一步。它们可帮助您将相关的Go源文件组织到一个单元中,使它们模块化,可重用和可维护。

*在本文中,您将学习如何将Go代码组织到可重复使用的程序包中,如何导入程序包,如何将函数,类型或变量导出到外部程序包以及如何安装第三方程序。

让我们开始吧!

Go 包

用最基本的术语来说,包只是Go工作区中包含一个或多个Go源文件或其他Go包的目录。

Go Package Illustration

每个Go源文件都属于一个包。要将源文件声明为包的一部分,我们使用以下语法-

package <packagename>

上面的包声明必须是Go源文件中的第一行代码。 Go源文件中定义的所有函数,类型和变量都将成为声明的包的一部分。

您可以选择将包中定义的成员导出到外部包,或将其私有化到同一包。其他软件包可以导入和重用从软件包中导出的功能或类型。

让我们看一个例子

到目前为止,我们在本教程系列(https://www.callicoder.com/categories/golang)中看到的几乎所有代码都包含以下行-

import "fmt"

fmt是一个核心库程序包,其中包含与格式化和打印输出或从各种I / O源读取输入有关的功能。它导出诸如Println()Printf()Scanf()等的函数,以供其他软件包重用。

以这种方式打包功能具有以下好处-

-减少命名冲突。您可以在不同的软件包中使用相同的函数名称。这使我们的函数名称简短明了。

-它可以将相关代码组织在一起,以便更轻松地找到要重用的代码。

-它只需要重新编译实际上已更改的程序的较小部分,即可加快编译过程。尽管我们使用fmt程序包,但无需在每次更改程序时都重新编译它。

main软件包和main()函数

Go程序开始在main软件包中运行。这是一个特殊的程序包,用于要执行的程序。

按照惯例,可执行程序(带有main软件包的程序)称为命令。其他简称为 Packages

main()函数是一个特殊函数,它是可执行程序的入口点。让我们来看一个Go语言中的可执行程序示例-

// 包声明
package main

// 导入包
import (
    "fmt"
    "time"
    "math"
    "math/rand"
)

func main() {
    // 找到两个数的最大值
    fmt.Println(math.Max(73.15, 92.46))

    // 计算数字的平方根
    fmt.Println(math.Sqrt(225))

    // 打印`𝜋`的值
    fmt.Println(math.Pi)

    // 纪元时间(以毫秒为单位)
    epoch := time.Now().Unix()
    fmt.Println(epoch)

    // 产生0到100之间的随机整数
    rand.Seed(epoch)
    fmt.Println(rand.Intn(100))
}
$ go run main.go
# 输出
92.46
15
3.141592653589793
1538045386
40

导入软件包

在Go中导入包有两种方法-

// 多个导入语句
import "fmt"
import "time"
import "math"
import "math/rand"
// 因式导入语句
import (
    "fmt"
    "time"
    "math"
    "math/rand"
)

Go的约定是-包名称与导入路径的最后一个元素相同。例如,导入为math / rand的软件包的名称是rand。它通过路径math / rand导入,因为它嵌套在math包中作为子目录。

导出与未导出的名称

任何以大写字母开头的内容(变量,类型或函数)都将导出,并在程序包外部可见。

任何不以大写字母开头的内容都不会导出,并且仅在同一软件包内可见。

导入软件包时,只能访问其导出的名称。

package main

import (
    "fmt"
    "math"
)

func main() {
    // MaxInt64是导出的名称
    fmt.Println("Max value of int64: ", int64(math.MaxInt64))

    // MaxInt64是导出的名称
    fmt.Println("Value of Phi (ϕ): ", math.Phi)

    // MaxInt64是导出的名称
    fmt.Println("Value of Pi (𝜋): ", math.pi)
}
# 输出
./exported_names.go:16:38: cannot refer to unexported name math.pi
./exported_names.go:16:38: undefined: math.pi

要解决以上错误,您需要将math.pi更改为math.Pi

创建和管理自定义包

到目前为止,我们仅在main程序包中编写了代码,并使用了从Go核心库程序包中导入的功能。

让我们创建一个示例Go项目,该项目具有多个带有一堆源代码文件的自定义包,并查看相同的包声明,导入和导出概念也如何应用于自定义包。

启动您的终端并为我们的Go项目创建目录:

$ mkdir packer

接下来,我们将创建一个Go模块,并将项目目录作为模块的根目录。

注意: Go模块是Go的新依赖项管理系统。模块是存储在目录中的Go软件包的集合,该软件包的根目录是go.mod **文件。 go.mod文件定义了模块的路径,这也是导入作为该模块一部分的软件包时使用的导入路径。

Go 1.11中引入Go模块之前,需要在所谓的[GOPATH]中创建每个项目(github.com/golang/go/wiki / GOPATH)。GOPATH内部项目的路径被视为其导入路径。

我们将在另一篇文章中详细了解Go模块。

通过键入以下命令来初始化Go模块:

$ cd packer
$ go mod init github.com/callicoder/packer

现在,我们创建一些源文件,并将它们放置在项目内的其他包中。下图显示了所有软件包和源文件:

Go custom package organization in Workspace

这是我们项目的每个源文件中的代码-

数字/prime.go

package numbers

import "math"

// 检查数字是否为质数
func IsPrime(num int) bool {
    for i := 2; i <= int(math.Floor(math.Sqrt(float64(num)))); i++ {
        if num%i == 0 {
            return false
        }
    }
    return num > 1
}

strings/reverse.go

package strings

// 反转一个字符串
/*
由于Go中的字符串是不可变的,因此我们首先将字符串转换为可变的符文数组([] rune),
对它执行相反的操作,然后重新广播为字符串。
*/
func Reverse(s string) string {
    runes := []rune(s)
    reversedRunes := reverseRunes(runes)
    return string(reversedRunes)
}

strings/reverse_runes.go

package strings

// 反转 runes 数组
// 这个函数没有对外暴露 (它只在 `strings` 包内可见)
func reverseRunes(r []rune) []rune {
    for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
        r[i], r[j] = r[j], r[i]
    }
    return r
}

strings/greeting/texts.go (嵌套包)

// 嵌套包
package greeting

// 对外暴露
const  (
    WelcomeText = "Hello, World to Golang"
    MorningText = "Good Morning"
    EveningText = "Good Evening"
)

// 不对外暴露 (仅在 `greeting` 包内可见)
var loremIpsumText = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad 
minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea 
commodo consequat.`

main.go (主程序包:程序的入口点)

package main

import (
    "fmt"
    str "strings" // Package Alias

    "github.com/callicoder/packer/numbers"
    "github.com/callicoder/packer/strings"
    "github.com/callicoder/packer/strings/greeting" // Importing a nested package
)

func main() {
    fmt.Println(numbers.IsPrime(19))

    fmt.Println(greeting.WelcomeText)

    fmt.Println(strings.Reverse("callicoder"))

    fmt.Println(str.Count("Go is Awesome. I love Go", "Go"))
}
# 构建 Go 模块
$ go build

上面的命令将产生一个可执行的二进制文件。让我们执行此二进制文件来运行程序:

# 执行二进制文件
$ ./packer
true
Hello, World to Golang
redocillac
2

注意事项

  • 导入路径

    所有导入路径都相对于模块的路径 [github.com/callicoder/packer](http://github.com/callicoder/packer).

    import (
        "github.com/callicoder/packer/numbers"
        "github.com/callicoder/packer/strings"  
        "github.com/callicoder/packer/strings/greeting"
    )
    
  • 包别名

    您可以使用包别名来解决不同的包却有相同的名称的冲突,或者只是为导入的包起一个简短的名字

    import (
        str "strings"   // 包别名
    )
    
  • 嵌套包

    您可以将一个包嵌套在另一个包中。这就像创建子目录一样简单 -

      packer
          strings          # 包
              greeting     # 嵌套包
                  texts.go
    

    嵌套包的导入方式类似于根包。只需提供其相对于模块路径的路径
     [github.com/callicoder/packer](http://github.com/callicoder/packer) -

    import (
        "github.com/callicoder/packer/strings/greeting"
    )
    

添加第三方包

使用 Go 模块将第三方包添加到您的项目中非常容易。您可以将包导入到项目中的任何源文件中,然后在下次构建/运行项目时,Go会自动为您下载 -

package main

import (
    "fmt"
    "rsc.io/quote"
)

func main() {
    fmt.Println(quote.Go())
}
$ go run main.go
go: finding rsc.io/quote v1.5.2
go: downloading rsc.io/quote v1.5.2
go: extracting rsc.io/quote v1.5.2
go: downloading rsc.io/sampler v1.3.0
go: extracting rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: extracting golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c

Don't communicate by sharing memory, share memory by communicating.

Go 还会将此新依赖项添加到 go.mod 文件中。

手动安装包

您可以使用 go get 命令从远程存储库下载第三方软件包。

$ go get -u github.com/jinzhu/gorm

上面的命令从 GitHub 获取 gorm 包,并将其作为依赖项添加到您的go.mod文件中。

就是这样。现在您可以像这样在程序中导入和使用上面的包 —

import "github.com/jinzhu/gorm"

结论

就这些了,朋友们!在本文中,您学习了如何将 Go 代码组织到可重用的包中,如何导入包,如何对外暴露包成员,如何创建自定义包以及如何安装第三方包。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://www.callicoder.com/golang-packag...

译文地址:https://learnku.com/go/t/47149

本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!