首页
Preview

使用 Go 进行 DevOps —— 你的第一个 Go 模块

在我上一篇Go文章中,我们学习了如何编写你的第一个Go“Hello World”程序。在这篇文章中,让我们开始学习构建Go应用程序的知识,这是我们继续学习Go语言的所有前提。

什么是Go模块

模块是一个Go包的集合,存储在一个文件树中,根目录下有一个go.mod文件。

一个Go模块包含两个特定的文件:go.modgo.sum

  • go.mod定义模块路径和依赖要求。例如:
module test.com/tony/hellomodule

go 1.19
require (
        github.com/valyala/fasthttp v1.41.0
        go.uber.org/zap v1.23.0
)
require (
        github.com/andybalholm/brotli v1.0.4 // indirect
        github.com/klauspost/compress v1.15.9 // indirect
        github.com/valyala/bytebufferpool v1.0.0 // indirect
        go.uber.org/atomic v1.7.0 // indirect
        go.uber.org/multierr v1.6.0 // indirect
)
  • go.sum是一个自动生成的依赖项锁定文件:
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
...
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

模块允许我们定义精确的依赖要求,并为多个环境设计可复制的构建。

第三方模块从它们的存储库下载到模块缓存中。在构建应用程序时,这些依赖项将从这些副本中加载。模块缓存默认位于主目录的go子目录中。

go.mod文件定义了模块的模块路径,这也是用于根目录的导入路径,以及其依赖要求,这是构建成功所需的其他模块。每个依赖要求都被写成一个模块路径和一个特定的语义版本。

一个模块有一个版本,因此模块下的包也有一个版本属性。这个模块和这些包将形成一个独立的版本单元,它们将一起进行版本控制、发布和分发。

在Go模块模式下,通常一个代码仓库对应一个Go模块。一个go.mod文件将被放置在Go模块的顶级目录中,每个go.mod文件将定义一个唯一的模块,这意味着Go模块和go.mod是一一对应的。

创建Go模块

创建模块目录

首先,在我们的godev目录中创建一个hellomodule文件夹:

$ pwd
/homex/tony/godev
$ mkdir hellomodule
$ cd hellomodule

初始化模块

现在让我们通过调用go mod init命令来初始化这个新模块:

$ go mod init test.com/hellomodule
go: creating new go.mod: module test.com/hellomodule

你应该会看到刚刚创建的go.mod文件:

$ ls
go.mod

$ cat go.mod
module test.com/hellomodule
go 1.19

由于这是一个新模块,我们还没有任何东西,这是预期的。

添加Go代码

现在让我们创建一个名为hellomodule.go的文件,内容如下:

package hellomodule

import "fmt"

// Hello returns a greeting for the named person.
func Hello(name string) string {
    message := fmt.Sprintf("Hello %v!", name)
    return message
}

在上面的代码中,我们实现了一个返回问候语字符串的Hello函数。请注意,在Go中,一个以大写字母开头的函数可以被不在同一个包中的函数调用。

导入Go模块

现在你已经创建了一个hellomodule的Go模块,让我们开始使用它。在godev文件夹中,创建另一个名为hello的目录。

$ mkdir hello
$ cd hello

创建一个名为hello.go的文件,内容如下:

package main

import (
    "fmt"
    "test.com/hellomodule"
)

func main() {
    message := hellomodule.Hello("Tony")
    fmt.Println(message)
}

如果你尝试运行这个hello.go,你会遇到以下错误:

$ go run hello.go
hello.go:6:5: no required module provides package test.com/hellomodule: go.mod file not found in current directory or any parent directory; see 'go help modules'

现在让我们为hello.go启用依赖跟踪:

$ go mod init test.com/hello
go: creating new go.mod: module test.com/hello
go: to add module requirements and sums:
        go mod tidy

在正常情况下,你应该只需要运行go mod tidy,它就会自动解决包依赖关系,但是,由于我们还没有发布我们的hellomodule,你会遇到以下错误:

$ go mod tidy
go: finding module for package test.com/hellomodule
test.com/hello imports
        test.com/hellomodule: cannot find module providing package test.com/hellomodule: unrecognized import path "test.com/hellomodule": https fetch: Get "https://test.com/hellomodule?go-get=1": net/http: TLS handshake timeout

为了解决这个问题,我们需要在这里进行一点小小的修改,也就是使test.com/hello模块能够在你的本地文件系统上找到test.com/hellomodule代码。让我们运行以下命令:

$ go mod edit -replace test.com/hellomodule=../hellomodule

现在让我们再次运行go mod tidy命令:

$ go mod tidy
go: finding module for package test.com/hellomodule
test.com/hello imports
        test.com/hellomodule: module test.com/hellomodule@latest found (v0.0.0-00010101000000-000000000000, replaced by ../hellomodule), but does not contain package test.com/hellomodule

go.mod的内容现在变成了:

$ cat go.mod
module test.com/hello

go 1.19

replace test.com/hellomodule => ../hellomodule

现在,我们应该能够运行hello.go,让我们试试:

$ go get test.com/hellomodule
go: added test.com/hellomodule v0.0.0-00010101000000-000000000000

$ go run hello.go
Hello Tony!

恭喜你!你已经构建了你的第一个Go模块!此时,你的godev文件夹结构应该如下所示:

$ tree
.
├── hello
│   ├── go.mod
│   └── hello.go
└── hellomodule
    ├── go.mod
    └── hellomodule.go

2 directories, 4 files

附录 —— Go模块命令

Go工具提供了几个与模块相关的命令。

go mod init - initializes new module in current directory
go mod tidy - adds missing and removes unused modules
go mod download - downloads modules to local cache
go mod vendor - makes vendored copy of dependencies
go mod graph - prints module requirement graph
go mod verify - verifies dependencies have expected content
go mod why - explains why packages or modules are need

译自:https://medium.com/geekculture/devops-in-go-your-first-go-module-71a02ebb5c3a

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
菜鸟一只
你就是个黄焖鸡,又黄又闷又垃圾。

评论(0)

添加评论