重学Go语言之如何使用Modules

 更新时间:2023年07月31日 16:04:11   作者:程序员读书  
Go语言在Go.1.11版本发布了Go Modules,这是一种新的Go项目依赖管理解决方案,可以让Go项目的依赖包关系更加清晰,也更容易管理,下面就来看看Modules是如何使用的吧

Module

Go Modules这种新的依赖机制中定义了Module这个概念,也就是所谓的模块

模块的组成

一个模块就是一个或者多个包(package)的集合,创建模块时,会在根目录下生成一个go.mod文件,go.mod文件包含了模块的路径(module path)以及该模块依赖的其他模块列表,在下载依赖模块后,还会生成一个go.sum文件,因此大体上,模块的构成如下图所示:

module path

module path,即模块路径,是该模块的身份标识,在模块内或者其他模块导入该模块的包时,必须以模块路径为前缀,比如模块路径为github.com/test/test,那么导入该模块的hello包时,则其导入的路径为:

import "github.com/test/test/hello"

下载依赖模块时也需要使用到模块路径:

go get github.com/test/test

语义化版本号

同一个模块可能会存在不同的版本,Go模块采用语义化版本号来定义模块的版本,其版本号格式为:

v<major>.<minor>.<patch>

  • major:主版本号,当模块做了不兼容的修改后,需更改主版本号。
  • minor:次版本号,当模块做了向下兼容的功能时,需要更改次版本号。
  • patch:修订版本号,当模块做了向下兼容的bug修改时,需要更改修订版本号。

前面我们使用go get命令下载依赖模块时并没有指定义版本号,那么默认下载master分支上最新的commit

go get github.com/test/test

如果指定版本号,且该版本号有对应的tag,那么就会下载对应的tag,如果没有对应tag,那么还是下载master分支上最新的commmit

go get github.com/test/test@v1.1.1

使用@latest可以下载最新版本的模块:

go get github.com/test/test@latest

当主版本号为v0或者v1时,在下载和导入时,可以省略版本号,当主版本大于或等于v2时,不可省略主版本号:

比如我们现在要下载有模块有v1.6.0v1.7.0以及v2.0.5三个版本,此时:

go get github.com/test/test
go get github.com/test/test@latest

上面的语句会下载v1.7.0,这是因为主版本v1版本可以省略且未指定版本,其效果与@latest一样。

因为1.6.0版本不是v1的最版本,所以要下载v1.6.0版本,则需要指定版本号:

go get github.com/test/test@1.6.0

如果要下载v2.0.5版本,下载路径为:

go get github.com/test/test/v2

创建一个新的模块

创建模块的命令为go mod init,该命令后面的参数就是模块路径,在目录名为hello的空目录执行以下语句:

$ go mod init example.com/hello

此时在hello目录会生成一个go.mod文件:

module example.com/hello
go 1.20

创建hello.go文件,代码如下:

package hello
func Hello() string {
    return "Hello, world."
}

创建hello_test.go文件,代码如下:

package hello
import "testing"
func TestHello(t *testing.T) {
    want := "Hello, world."
    if got := Hello(); got != want {
        t.Errorf("Hello() = %q, want %q", got, want)
    }
}

运行go test命令:

$ go test
PASS
ok      example.com/hello       0.024s

这样,我们就已经创建了一个自己的模块。

依赖其他的模块

Go Modules的作用就在于定义与规范了模块之间的版本依赖关系,通过这套机制,我们可以在自己的模块中导入其他的模块。

现在我们假设有一个其他开发者创建好的模块:github.com/test/MyUtil,该模块当前的版本为v1.13,我们使用import语句导出,并在Hello()方法中使用:

package hello
import "github.com/test/MyUtil"
func Hello() string {
    return MyUtil.Hello()
}

现在代码还不能运行,因为我们还没将该模块下载到本地,下载依赖的模块使用go get命令:

$ go get github.com/test/MyUtil
go: downloading github.com/test/MyUtil v1.1.3
go: added github.com/test/MyUtil v1.1.3

下载了依赖的模块之后,go.mod文件会记录当前模块的依赖项:

module example.com/hello
go 1.20
require github.com/test/MyUtil v1.1.3

另外,下载依赖模块时也会生成一个go.sum文件,其内容如下:

github.com/test/MyUtil v1.1.3 h1:A2x2RDcKl0rxZaOKk0Mn71HQfISoS/0Vex+UHjtou4o=
github.com/test/MyUtil v1.1.3/go.mod h1:8PqlR4GowL1as1JuS979xEp6TmJjrCIG+Bnjrdo3bfE=

go.sum文件在下载依赖时会发生变化,每个依赖模块可能会生成两行记录,一行表示依赖模块的全体文件的SHA-256哈希值,另一行则为依赖模块的go.mod文件的哈希值。

再次运行go test命令:

$ go test
PASS
ok      example.com/hello       0.024s

现在,我们就已经成功在自己的模块中调用其他模块的功能了。

升级依赖的模块

我们依赖的模块也会更新升级,现在假设模块MyUtil增加了其他函数,并且版本升级到v.1.12.10,我们可以调用go get命令模块版本升级。

在模块路径后面可以指定义升级的版本:

 go get github.com/test/MyUtil@1.12.10

也可以在路径后直接跟上@latest升级最新的版本:

github.com/test/MyUtil@latest 

因为当前最新版本为v1.12.10,因此上面两种路径的效果是一样的:

$ go get github.com/test/MyUtil@latest  
go: downloading github.com/test/MyUtil v1.12.10
go: upgraded github.com/test/MyUtil v1.1.3 => v1.12.10

go.mod文件可以看出依赖模块版本的变化:

module example.com/hello
go 1.20
require github.com/test/MyUtil v1.12.10

添加一个新的主版本

当模块的主版本号发生变化时,比如从v1升级到v2,说明新版本做出之前不兼容的变更,我们可以通过在模块路径后面跟上版本来下载对应的版本:

 go get github.com/test/MyUtil/v2

此时import语句后面的路径也发生了变化:

package hello
import (
 "github.com/test/MyUtil"
 v2 "github.com/test/MyUtil/v2"
)
func Hello() string {
 return MyUtil.Hello()
}
func Hello2() string {
 return v2.HelloV2("%s", "Hello")
}

小结

Go Module是一种比较复杂的依赖解决方案,今天的这篇文章算是讲解了Go Modules的基本使用与一些基本概念,没有涉及到Go Modules的全部知识,在以后的文章,我们再详细展开。

到此这篇关于重学Go语言之如何使用Modules的文章就介绍到这了,更多相关Go Modules内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • golang结构化日志slog的用法简介

    golang结构化日志slog的用法简介

    日志是任何软件的重要组成部分,Go 提供了一个内置日志包(slog),在本文中,小编将简单介绍一下slog包的功能以及如何在 Go 应用程序中使用它,感兴趣的可以了解下
    2023-09-09
  • Go使用协程批量获取数据加快接口返回速度

    Go使用协程批量获取数据加快接口返回速度

    这篇文章主要介绍了Go使用协程批量获取数据加快接口返回速度,使用Go语言后,可以并发获取,极大提升效率,需要的朋友可以参考下
    2023-02-02
  • go语言中http超时引发的事故解决

    go语言中http超时引发的事故解决

    我们使用的是golang标准库的http client,对于一些http请求,我们在处理的时候,会考虑加上超时时间,如果超时可能会引起报错,本文就记一次超时引发的事故
    2021-06-06
  • Go语言实现一个Http Server框架(二) Server的抽象

    Go语言实现一个Http Server框架(二) Server的抽象

    上一篇文章对http库的基本使用做了说明,这篇文章主要介绍了如何实现一个简单地httpServer,文中代码示例非常详细,感兴趣的朋友可以参考下
    2023-04-04
  • GO使用socket和channel实现简单控制台聊天室

    GO使用socket和channel实现简单控制台聊天室

    今天小编给大家分享一个简单的聊天室功能,聊天室主要功能是用户可以加入离开聊天室,实现思路也很简单明了,下面小编给大家带来了完整代码,感兴趣的朋友跟随小编一起看看吧
    2021-12-12
  • Golang中List的实现方法示例详解

    Golang中List的实现方法示例详解

    最近决定复习下Go,所以下面这篇文章主要给大家介绍了关于Golang中List的实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-09-09
  • golang实现跨域访问的方法

    golang实现跨域访问的方法

    这篇文章主要介绍了golang实现跨域访问的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • Golang 统计字符串字数的方法示例

    Golang 统计字符串字数的方法示例

    本篇文章主要介绍了Golang 统计字符串字数的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • goland 恢复已更改文件的操作

    goland 恢复已更改文件的操作

    这篇文章主要介绍了goland 恢复已更改文件的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • golang实现大文件读取的代码示例

    golang实现大文件读取的代码示例

    在实际工作,我们需要读取大数据文件,文件可能上G百G,所以我们不可能一次性的读取到内存,接下来本文给大家介绍了golang实现大文件读取的示例,需要的朋友可以参考下
    2024-04-04

最新评论