~/go。src:存放源代码,包括项目自身和所有第三方依赖的源码。pkg:存放编译后的包文件(.a)。bin:存放编译后的可执行文件。go get 时,依赖库的源代码被下载到 GOPATH/src 目录下。编译器查找依赖时,也仅从这个路径查找。
核心局限:无法处理多版本依赖由于GOPATH/src下每个包只能存在一个版本,如果两个项目 A 和 B 需要同一个库 T 的不同版本,必然发生冲突,这在复杂的工程协作中是不可接受的。
GOPATH/
├── src/ # 源代码(你的项目+所有依赖)
├── pkg/ # 编译后的包文件
└── bin/ # 可执行文件// 假设GOPATH=/home/user/go
// 你的项目路径必须是:/home/user/go/src/myproject/main.go
package main
import (
"github.com/gin-gonic/gin" // 编译器会在GOPATH/src中找这个包
)
func main() {
r := gin.Default()
r.Run()
}项目A:需要 github.com/lib/pq v1.0
项目B:需要 github.com/lib/pq v2.0
但在GOPATH/src/github.com/lib/pq 只能放一个版本!GOPATH/src 路径下才能被 Go 工具链识别和编译。这与现代软件开发中项目可以放置在任意位置的习惯相悖。vendor 的子目录。vendor 目录中。vendor 目录,如果找不到或该机制未启用,才会回退到 GOPATH 中查找。
myproject/
├── main.go
└── vendor/ # 项目私有的依赖
└── github.com/
└── gin-gonic/
└── gin/ # 项目专用的gin版本vendor 目录,过程繁琐,容易出错。缺乏统一的工具来自动化管理依赖图。go.mod)来声明项目所需的精确版本。依赖信息隐藏在 vendor 目录的物理文件中,难以追溯和审计。# 手动管理依赖很痛苦
cp -r $GOPATH/src/github.com/gin-gonic/gin ./vendor/
# 更新依赖?删除重新拷贝?
# 依赖的依赖?也要手动处理!# 可以在任何目录创建项目,不再需要GOPATH!
mkdir myproject && cd myproject
go mod init github.com/yourname/myprojectmodule github.com/yourname/myproject
go 1.20vendor 目录或全局的 GOPATH/src 中。而是统一存储在 GOPATH/pkg/mod 目录下。不同版本的同一个依赖被隔离存放,实现了多版本共存。
go.mod 和 go.sum 文件,项目精确地锁定了直接和间接依赖的版本。这保证了构建的可重复性,无论在任何机器上,都能得到相同的构建结果。go mod init:初始化模块。go mod tidy:清理和同步依赖列表。go get module@version:精确地更新依赖版本。最佳实践:全面采用 Go ModuleGo Module 解决了 Go 依赖管理长期以来的核心痛点,提供了版本锁定、高效缓存、以及对语义化版本的原生支持。建议所有新老 Go 项目都迁移到 Go Module,以确保构建的稳定性和可维护性。