参考
go 官方文档
Go语言重新开始,Go Modules 的前世今生与基本使用
是什么
go mod 是 go 在 1.11 后提供的 go 包管理工具,和前段中的 npm 具有一样的功能。而在此之前 go 需要通过 gopath 来进行包管理,因为太过麻烦,所以现在更多的是使用 mod 的方式。
在 go 1.16 之后,已经默认 Go111MODULE=on 为默认值,也就是默认使用 go module 进行依赖管理。
注意
⚠ 本文的环境是 go 1.16
创建一个 go module
选择一个目录,比如现在我在 D:codego_projectstudygomod_study 下创建一个 greetings 文件夹。进入这个文件夹后,我们通过 go mod init xxx 的语法来创建 modlue。
go mod init example.com/greetings
此时,你的 greetings 文件夹中将会自动生成 go.mod 文件,文件的内容如下:
module example.com/greetings
go 1.16
这个时候 mod 就成功被建立起来了。
引用本地的 mod 之一
在开发中,有时我们需要引用自己的,本地的模块(mod),换句话说,你的这个模块(mod)并没有上传到 github 上,不能通过 go get github.com/example/exampleMod 这样下载后,通过 import "github.com/example/exampleMod" 的方式使用。下面就是这个板块的内容。
mod 就像一个模块,你可以调用已有的 mod ,并使用它所提供的方法。有时候,你可以把写好的 mod 发布出去,让别人使用你的 mod,但是在这里,我们先假设 mod 未被发布出去,即我们要先看看怎么从本地来引用我们写好的 mod。
还是在 greetings 文件夹中,我们新建一个 greetings.go 的文件,并在里面写一个简单的 Hello 函数。
package greetings
import "fmt"
func Hello(name string) string {
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message
}
然后我们在创建一个和 greetings 文件夹同级的 hello 文件夹,同时在 hello 文件夹中开启 mod(go mod init example.com/hello),以及创建一个 hello.go 的文件。现在的目录情况如下:
D:.
├─greetings
│ go.mod
│ greetings.go
│
└─hello
go.mod
hello.go
在 hello.go 中我们写如下的代码
package main
import (
"fmt"
// 格式:引用的 mod 名字
"example.com/greetings"
)
func main() {
// Get a greeting message and print it.
message := greetings.Hello("Gladys")
fmt.Println(message)
}
在这里我们除了引入了 fmt 包(内置包),还引入了 example.com/greetings 包,当然此时是会报错的,因为 example.com/greetings 包所在的 mod 并不是我们当前 hello 所用的模块。
我们为了使用 example.com/greetings 中的 Hello 函数,则需要将 example.com/greetings 和 example.com/hello 这两个模块关联起来。
通过 go mod edit -replace example.com/greetings=../greetings 我们将 example.com/greetings 模块引入,在 go.mod 文件中我们会发现文件自动更改为了下面的内容。
module example.com/hello
go 1.16
replace example.com/greetings => ../greetings
replace 的作用就是用于模块的替换,你可以在官方文档中进行更深入的学习。
其中这句话的左边是替换的自定义的名字,右边则是要被替换的模块的路径,greetings 为文件夹的名字。
此时,hello 模块已经引入了 greetings 模块,但是还没有完,接着我们还要使用 go mod tidy 命令,然后 go.mod 文件内容又变成了下面这样:
module example.com/hello
go 1.16
replace example.com/greetings => ../greetings
require example.com/greetings v0.0.0-00010101000000-000000000000
到这里,我们已经成功地引用了 example.com/greetings 模块。
这里用到的 go mod tidy命令的作用是,确保 go.mod 文件与模块中的源代码匹配,添加缺失的依赖,删除未使用的依赖。
此时在命令行中运行命令 go run . ,则输出结果 Hi, Gladys. Welcome!
引用本地的 mod 之二
与上面的本地的 mod 的含义不同,这里指的是之前的项目中已经下过了的 mod,我们如何使用。
比如,在之前的项目中,我们已经通过 go get 下载了某个包,现在要在新项目中使用这个包,只需要直接 go get thismod@对应版本,比如,go get github.com/go-sql-driver/mysql@v1.4.1,就可以了,这里并不会重复下载,而是先检查本地是否已经存在需要的版本,如果有就直接引用。
引用包(package)的情况之一
存在于同一项目(mod) 中的,不同的包
D:.
│ go.mod
│ main.go
│
└─util
familyAccount.go
这是 main.go 的文件,它属于 main 包
package main
import (
// 调用嵌套的本地包的语法是 "modName/packageName"
"MyAccount/util"
)
func main() {
util.NewFamliyAccount().ShowMenu()
}
这是 familyAccount.go 的文件,它属于 util 包
package util
import "fmt"
// 省略了该文件中的代码,因为不重要,你只要知道下面的方法的调用链如上面的 main() 中所示
// 这里有一个工厂方法 NewFamliyAccount() 返回一个实例
// 这个实例有一个 ShowMenu() 的方法
这是 mod.go 文件
module MyAccount
go 1.16
引用包(package)的情况之二
情况三:多级目录
在情况二的背景下,如果我们的项目结构是多级目录,如下:
D:.
│ go.mod
│ main.go
│
└─util
└─ util01
familyAccount.go
在 familyAccount.go 中,我们将 util01 作为包名,也就是距离 .go 文件最近的文件夹的名字作为包名
package util01
// 其他业务代码 ...
其实想要在 main.go 中引入的方式还是一样的
import (
"MyAccount/util/util01"
)
模块版本号
我们在前面代码块中的最后一行,看到了 greetings 模块的版本号,即 require example.com/greetings v0.0.0-00010101000000-000000000000。
在 go 中,模块的版本号用于向其他开发人员描述当前模块的一些信息,如稳定性,是否向后兼容,而模块的开发人员在发布模块的时候,则需要通过版本号传达出这些信息,所以一个模块号是遵循一定命名规则的。

go 官方稳定提供了的下表描述了版本号的各个部分如何表示模块的稳定性和向后兼容性。
| 版本阶段 | 举例 | 含义 |
|---|---|---|
| 在开发中 | 自动伪版本号 v0.x.x | 表示模块仍在开发中且不稳定的信号。此版本不提供向后兼容性或稳定性保证。 |
| 主版本号 | v1.x.x | 表示向后不兼容的公共 API 更改。此版本不保证将向后兼容之前的主要版本。 |
| 次版本号 | vx.4.x | 表示向后兼容的公共 API 更改。此版本保证向后兼容性和稳定性。 |
| 补丁版本 | vx.x.1 | 通知不影响模块的公共 API 或其依赖项的更改。此版本保证向后兼容性和稳定性。 |
| 预发布版本 | vx.x.x-beta.2 | 表示这是一个预发布里程碑,例如 alpha 或 beta。此版本不提供稳定性保证。 |
在开发中的版本有两种版本号,一种是伪版本号 v0.0.0-20170915032832-14c0d48ead0c,另一种是 v0 版本 v0.x.x。不过在开发中优先选择自动生成的伪版本号为最佳实践。
引用外部的 mod
引用外部的 mod 有两种,一种是官方内置的,如 fmt,net 等,这些包只需要直接 import 即可。
另一种是第三方的,下面我们来看看。
比如我现在引用第三方的 mod “rsc.io/quote” 这个 mod,首先我要先下载这个 mod,其方法如下,在当前目录下执行 go get rsc.io/quote,rsc.io/quote 这个包会被下载到 GOPATH/pkg/mod 这个路径下,而它对应的 checksum(校验和) 数据会被下载到 GOPATH/pkg/sumdb 中,并且在当前项目中会生成 go.sum。
其对应的 go.mod 会自动生成为
module example.com/hello
go 1.16
require (
rsc.io/quote v1.5.2 // indirect
)
在这个 mod 中提供了一个 func Hello() string函数,我们来调用一下,最终输出“你好,世界”
package main
import (
"fmt"
"rsc.io/quote"
)
func main() {
fmt.Println(quote.Hello()) // 你好,世界。
}
参考与拓展
Go Modules Reference
Using “replace” in go.mod to point to your local module
Go版本依赖–伪版本
最后
以上就是健忘小白菜最近收集整理的关于go mod基础 学习笔记参考是什么注意创建一个 go module引用本地的 mod 之一引用本地的 mod 之二引用包(package)的情况之一引用包(package)的情况之二模块版本号引用外部的 mod参考与拓展的全部内容,更多相关go内容请搜索靠谱客的其他文章。
" 和 “." 有什么区别?" class="embed-responsive-item">
发表评论 取消回复