1. 工作区是磁盘上模块的集合,在运行最小版本选择(MVS)时用作根模块。
  2. 工作空间可以在go.work文件中声明,该文件指定工作空间中每个模块的模块目录的相对路径。
  3. 当不存在go.work文件时,工作区由包含当前目录的单个模块组成。
  4. 大多数与模块一起使用的go子命令在由当前工作空间确定的模块集上运行。
  5. go mod initgo mod whygo mod editgo mod tidygo mod vendorgo get始终在单个主模块上运行。
  6. 命令首先检查-workfile标志来确定它是否在工作区上下文中。如果-workfile设置为off,则该命令将位于单模块上下文中。
  7. 如果它为空或未提供,该命令将搜索当前工作目录,然后是后续父目录,以查找文件go.work。如果找到一个文件,该命令将在它定义的工作空间中运行;
  8. 否则,工作区将仅包含包含工作目录的模块。如果-workfile命名以.work结尾的现有文件的路径,则将启用工作区模式。任何其他值都是错误。
  9. go.work文件一般不传到git上,只是本地一个公共区文件。

go.work文件

  1. 工作空间由名为go.work,UTF-8编码文本文件定义。
  2. go.work文件是面向行的。每行包含一个指令,由关键字参数组成。 例如:
go 1.18

use ./my/first/thing
use ./my/second/thing

replace example.com/bad/thing v1.4.5 => example.com/good/thing v1.4.5
  1. 与go.mod文件一样,可以从相邻行中分解出前导关键字来创建块。
use (
    ./my/first/thing
    ./my/second/thing
)
  1. go命令提供了几个用于操作go.work文件的子命令。
    • go work init:创建新的go.work文件。
    • go work use:将模块目录添加到go.work文件中。
    • go work edit:执行低级编辑。
    • go work sync:将工作区构建列表同步到模块。
  2. Go程序可以使用golang.org/x/mod/modfile包以编程方式进行相同的更改。

词汇元素

  1. go.work文件中的词法元素的定义方式与go.mod文件完全相同。

语法

  1. go.work语法在下面使用扩展巴科斯-瑙尔形式(EBNF)指定。有关EBNF语法的详细信息,请参阅Go语言规范中的符号部分。
1
2
3
4
GoWork = { Directive } .
Directive = GoDirective |
            UseDirective |
            ReplaceDirective .
  1. 换行符(newline)、标识符(ident)和字符串(string)分别表示。
  2. 模块路径和版本用ModulePath和Version表示。模块路径和版本的指定方式与go.mod文件完全相同。
1
2
ModulePath = ident | string . /* see restrictions above */
Version = ident | string .    /* see restrictions above */

go指令

  1. 有效的go.work文件中需要go指令。版本必须是有效的Go发行版本:一个正整数,后跟一个点和一个非负整数(例如,1.18、1.19)。
  2. go指令指示go.work文件打算使用的go工具链版本。如果对go.work文件格式进行了更改,工具链的未来版本将根据其指示的版本解释文件。
  3. 一个go.work文件最多可以包含一个go指令。
1
2
GoDirective = "go" GoVersion newline .
GoVersion = string | ident .  /* valid release version; see above */
  1. 示例:
go 1.18

use指令

  1. 用户将磁盘上的模块添加到工作空间中的主要模块集。它的参数是包含模块的go.mod文件的目录的相对路径。
  2. 使用use指令不会添加包含在其参数目录的子目录中的模块。
  3. 这些模块可以通过包含其go.mod文件的目录添加到单独的使用指令中。
1
2
3
UseDirective = "use" ( UseSpec | "(" newline { UseSpec } ")" newline ) .
UseSpec = FilePath newline .
FilePath = /* platform-specific relative or absolute file path */
  1. 示例:
use ./mymod  // example.com/mymod

use (
    ../othermod
    ./subdir/thirdmod
)

replace指令

  1. 与go.mod文件中的replace指令类似,go.work文件中的replace指令将模块的特定版本或模块的所有版本的内容替换为其他地方的内容
  2. go.work中的通配符替换会覆盖go.mod文件中特定于版本的替换。
  3. go.work文件中的replace指令会覆盖工作区模块中相同模块或模块版本的任何替换。
1
2
3
4
ReplaceDirective = "replace" ( ReplaceSpec | "(" newline { ReplaceSpec } ")" newline ) .
ReplaceSpec = ModulePath [ Version ] "=>" FilePath newline
            | ModulePath [ Version ] "=>" ModulePath Version newline .
FilePath = /* platform-specific relative or absolute file path */
  1. 示例:
replace golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5

replace (
    golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
    golang.org/x/net => example.com/fork/net v1.4.5
    golang.org/x/net v1.2.3 => ./fork/net
    golang.org/x/net => ./fork/net
)

错误的go.work

  1. 同时在use和replace指定相同的本地路径。同时指定./example
go 1.18

use (
    ./hello
    ./example
)

replace (
    github.com/link1st/example => ./example
)