golang包和依赖管理 | 青训营笔记

401 阅读3分钟

这是我参与「第五届青训营」伴学笔记创作活动的第2天。今天复习了go的包和依赖管理相关内容,并将一些值得注意的点记录了下来。

golang包

包可以区分命令空间(一个文件夹中不能有两个同名文件),也可以更好的管理项目。go中创建一个包,一般是创建一个文件夹,在该文件夹里面的go文件中,使用package关键字声明包名称,通常,文件夹名称和包名称相同。并且,同一个文件下面只有一个包

注意

  • 一个文件夹下只能有一个package
    • 注意,这里指的是“直接包含”的go文件。如果有子目录,那么子目录的父目录是完全两个包。
  • 一个package的文件不能在多个文件夹下
    • 如果多个文件夹下有重名的package,它们其实是彼此无关的package。
    • 如果一个go文件需要同时使用不同目录下的同名package,需要在import这些目录时为每个目录指定一个package的别名。

go依赖管理演进

GOPATH -> Go Vendor -> Go Module

GOPATH

  • GOPATH是go语言中的一个环境变量,使用绝对路径提供项目的工作目录。在 GOPATH 指定的工作目录下,代码总是会保存在 GOPATH/src 目录下。
  • 在工程经过 go build、go install 或 go get 等指令后,会将产生的二进制可执行文件放在 GOPATH/bin 目录下,生成的中间缓存文件会被保存在 GOPATH/pkg 下。
  • 如果需要将整个源码添加到版本管理工具(Version Control System,VCS)中时,只需要添加 GOPATH/src 目录的源码即可。bin 和 pkg 目录的内容都可以由 src 目录生成。
  • GOPATH的问题主要是无法实现包的多版本控制。如果两个项目依赖于某一个包的不同版本,会发生不能同时将两个项目构建成功的问题。

Go Vendor

  • 项目目录下增加vendor文件,所有依赖包以副本形式放在ProjectRoot/vendor
  • 通过每个项目引入一份依赖的副本,解决了多个项目需要同一个包依赖的冲突问题。
  • 弊端是如果项目间接依赖了一个包的不同版本,会发生不兼容的问题。主要原因是不能清晰地标识依赖包的版本。

Go Module

  • 主要目标是定义版本规则和管理项目依赖关系。通过go.mod文件管理依赖包的版本,通过go get/go mod指令工具管理依赖包。
  • go Module的依赖管理三要素:
    • 配置文件go.mod描述依赖
      • 模块路径、原生库、单元依赖
      • 依赖标识:[模块路径][版本号]
        • 版本定义:
          • 语义化版本:{major}.{minor}.{patch} 比如v1.2.3
          • 基于commit伪版本: {prefix}-{timestamp}-{hash}
      • indirect:间接依赖
      • incompatible:没有go.mod文件并且主版本2+的依赖的标识
      • 在选定依赖包版本时会选择最低兼容版本。
    • 中心仓库Proxy管理依赖库
      • 直接使用第三方依赖分发无法保证构建的稳定性和依赖可用性,即作者可以随意地增加、修改、删除软件版本,同时增加第三方平台的负载问题。
      • Proxy会缓存第三方软件包的各版本,从而找到软件路径。go通过指定PROXY变量来标识服务站点的url列表,其中direct标识源站。
    • 本地工具go get/mod
      • go get example.org/pkg
        • @update 默认major版本最新的提交
        • @none 删除依赖
        • @v1.1.2 tag语义版本
        • @23dfdd5 特定的commit
        • @master 分支的最新commit
      • go mod
        • init 初始化,创建go.mod文件
        • download 下载模块到本地缓存
        • tidy 增加需要的依赖,删除不需要的依赖