在我上一篇Go文章中,我们学习了如何编写你的第一个Go“Hello World”程序。在这篇文章中,让我们开始学习构建Go应用程序的知识,这是我们继续学习Go语言的所有前提。
什么是Go模块
模块是一个Go包的集合,存储在一个文件树中,根目录下有一个go.mod
文件。
一个Go模块包含两个特定的文件:go.mod
和go.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
评论(0)