GO 依赖管理和工作区管理丨青训营笔记

160 阅读5分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 5 天

(这是之前的,好像发在同一天没算上打卡,所以重发了)

本文同步发布于博客(xblc.netlify.app),如果有更新博客会在第一时间更新

官方文档:Using Go Modules - The Go Programming Language

由来&前置

大概就是有两种依赖管理系统的演变,最终现在最优的依赖管理模式就是 Go Modules

最早的那种模式是直接去 GOPATH 里面找,也就是GoLang的安装目录,这种方法假设我们某个项目需要一个特定版本的包就无法管理了

然后就有一个办法,项目目录下直接开一个文件夹来存依赖,这样总行了吧。但是当我们有另一个项目同时需要依赖两个这样的项目的时候,两个项目对应的依赖可能会不兼容,即无法实现版本管理

然后 Go Modules 这种最新的模式就出现了,整体思想就是用一个文件 go.mod 来管理依赖版本,然后用命令工具去控制这些版本 (通过命令 go mod tidy 下载的模块应该也是集中存在特定位置了)

go.mod 是伴随着你源码的一个不断更新的依赖管理文件

go mod init [module path] 启用依赖管理,模块路径表示现在写的这个模块的路径,如果是远程仓库的话就得是一个可下载的未知;细致的命名规范:Managing dependencies

go.sum 是用来校验我们下载的模块的

模块、包、函数(代码)

  • 逐渐包含的关系
  • Package 是组织函数的一种方式,由同一个文件夹里面所有的函数构成

包名主要和文件夹名(定位)和包声明(包名)有关,和源代码名称无关(随便改只要声明正确就能找到)

认识工作区

模块路径、模块名、文件夹名、文件名的区别:

  • 模块路径:每个模块 go.mod 文件中 module 关键字后面的,一般会是 Github 仓库地址或者Go仓库地址,是导入的时候为了能直接从网上或者是本地找到的,也是 go init [MODULE PATH] 时候的最后一个参数

  • 模块名:也是文件夹名或者一般是路径最后的那个名字。有个要点是一次只能导入一个包,不能导入一整个模块。

  • 文件名:暂时没发现有什么用,可以继续归结一下函数的名字们倒是;然后叫做同一个包名的文件可以共享函数,也就是说文件就是包的进一步分解,最小的那个文件夹就是一个包,然后包里面的文件都必须标好这个包名,然后就随便了,可以看成一个整体;main在谁里面没关系,在哪个文件里导入包也没关系

    image-20230121174014026

工作区的逻辑层次大概是这样的:工作区 > 模块 > 包 > 函数

  • 包是代码运行的最小单位,由一个文件夹构成
  • 有模块的话 go.mod 文件应该在模块的文件夹对该模块下的所有包进行管理
  • 模块是我们一般进行开发的主要单位,里面会有不同的包相互配合,一个模块里面只有一个 main 包,是整个包的入口

工作区是 Golang 1.18 的新特性,最大的作用就是允许我们对相互依赖的「模块」进行开发

我没理解错的话,工作区就是使得我们恰好对几个功能逻辑上相互独立,但依然有点关联的一些模块进行了更高一层的抽象统一,可以适当节省一些资源。

工作区的使用

  • 如果我们要导入的包,在工作区中已经存在了(下载下来了,和模块在同级目录),那会优先使用工作区中的本地模块(测试新加的函数可以用),类似于 GO Ventor 的逻辑(这个时候 go.mod 没有存依赖的版本,也就是不需要 go get ;这是因为导入包的时候也有一个类似于系统 PATH 变量的逻辑,会依次从安装目录、当前工作区、直接网络访问那个路径来寻找

  • 创建了工作区以后,即已经有了 go.work 文件,那么没有加入工作区的模块都不会被视作是模块,使用本地工具的时候会有很多诧异的报错

待刷: 官方博文:Go 1.18 工作区模式最佳实践 - 知乎

杂谈

  • Tutorial: Getting started with multi-module workspaces - The Go Programming Language 这里面其实也没学啥,可能工作区管理就是一种管理好多个模块,让其一起工作的逻辑吧

    这个教程就是让你建一个模块,然后上级建立一个工作区,然后在工作区再拉取一个模块,然后修改这个拉取的模块,在原来的模块里面重新调用修改的模块

  • 在把库里的包下载到本地然后用相对路径导入的话,有一个暂时还没懂的问题,导入的时候我们是用 路径/模块/包 这样导入的,然而下载到本地的时候 go.mod 也很合理地出现在了模块路径中,导致本地导入的时候会报错

    stringutil: module ../example/stringutil: reading ..\example\stringutil\go.mod: open D:\Codes\GoCodes\testcodes\example\stringutil\go.mod: The system cannot find the file specified.

    就是没有找到 go.mod 文件,就很奇怪,看来依赖管理还没学好,特别是关于整个模块的依赖管理