在 Go 项目中使用go mod作为依赖管理工具,go.mod文件是其核心配置文件。

一般情况下,go.mod的配置项主要有:module go require,大概结构如下:

module github.com/project/demo

go 1.24.0

require (
    github.com/gin-gonic/gin v1.10.1
    gorm.io/driver/sqlite v1.6.0
    gorm.io/gorm v1.30.1
)

require (
    github.com/bytedance/sonic v1.11.6 // indirect
    github.com/bytedance/sonic/loader v0.1.1 // indirect
    github.com/goccy/go-json v0.10.2 // indirect
    github.com/pelletier/go-toml/v2 v2.2.2 // indirect
    ... // 省略其他依赖
)

上面这个go.mod是通过go mod tidy整理后的,可以看出有两段require配置,require中列出了该项目所有的依赖项及其版本。

直接依赖

require (
    github.com/gin-gonic/gin v1.10.1
    gorm.io/driver/sqlite v1.6.0
    gorm.io/gorm v1.30.1
)

第一段require表示是项目的直接依赖,就是代码中通过import引用的依赖,就会在这个部分列出,这些依赖是项目的直接依赖。一般我们看一个项目有哪些依赖项,主要看这部分。

间接依赖

require (
    github.com/bytedance/sonic v1.11.6 // indirect
    github.com/bytedance/sonic/loader v0.1.1 // indirect
    github.com/goccy/go-json v0.10.2 // indirect
    github.com/pelletier/go-toml/v2 v2.2.2 // indirect
    ... // 省略其他依赖
)

第二段require表示项目的间接依赖,在结尾都标记有indirect,就是项目的源码中没有直接import过的,而是第一部分依赖中的依赖,就是传递过来的间接依赖,在大项目中,间接依赖通常很多。

最后

自 Go 1.17 之后,使用go mod tidy进行整理后,会自动将直接依赖和间接依赖区分开来,并且列出了项目中所有的间接依赖,有点类似npmcomposer.lock的意思,确保所有依赖有固定的版本,避免后续升级带来的不可确定的兼容问题。

其实go.mod也不一定只能有两段require,也可以自行分组,看到网上一篇文章介绍三段式require结构,就是加入了一段单独声明的间接依赖,比如为了解决特定问题,要单独指定一个间接依赖的版本就可以在这一段完成。当然如果要自行指定间接依赖版本直接加在第一段就可以了,带上// indirect标记,它并不会被go mod tidy修剪掉。

随着Go的发展,go mod依赖管理越来越完善,简单而不失灵活。