工作区

Workspaces 工作区

原文:https://go.dev/ref/mod#workspaces

​ 工作区是磁盘上模块的集合,在运行minimal version selection (MVS) (最小版本选择(MVS))时这些模块被用作主模块。

​ 工作区可以在 go.work 文件中声明,该文件指定了工作区中每个模块目录的相对路径。当没有go.work文件存在时,工作区由包含当前目录的单个模块组成。

​ 大多数处理模块的go子命令都是在由当前工作区决定的模块集合上操作的。go mod initgo mod whygo mod editgo mod tidygo mod vendorgo get总是在一个主模块上操作。

​ 命令首先通过检查GOWORK环境变量来确定它是否处于工作区上下文中。如果GOWORK被设置为off,该命令将处于单模块上下文中。如果它是空的或者未提供,命令将在当前工作目录中搜索,然后在连续的父目录中搜索go.work这个文件。如果找到一个(go.work)文件,该命令将在该文件定义的工作区中操作;否则,工作区将只包括包含工作目录的模块。如果GOWORK命名一个以.work结尾的现有文件的路径,工作区模式将被启用。任何其他的值都是一个错误。您可以使用go env GOWORK命令来确定go命令正在使用哪个go.work文件。如果go命令没有进入工作区模式,go env GOWORK将为空。

go.work files

​ 工作区是由一个名为go.work的UTF-8编码文本文件定义的。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

​ 与go.mod文件一样,前导关键字可以从相邻的行中分解出来,形成一个块。

use (
    ./my/first/thing
    ./my/second/thing
)

go命令提供了几个操作go.work文件的子命令。go work init创建新的go.work文件。go work usego.work文件添加模块目录。go work edit执行低级别的编辑。Go 程序可以使用 golang.org/x/mod/modfile 包,以编程方式进行相同的更改。

Lexical elements 词汇元素

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

Grammar 语法

go.work的语法由下面使用Extended Backus-Naur Form (EBNF)来指定。有关 EBNF 语法的详细信息,请参见 Go 语言规范中的标记法部分

GoWork = { Directive } .
Directive = GoDirective |
            UseDirective |
            ReplaceDirective .

​ 换行符、标识符和字符串分别用newlineidentstring表示。

​ 模块路径和版本用ModulePathVersion来表示。模块路径和版本的指定方式与go.mod文件的指定方式完全相同。

ModulePath = ident | string . /* see restrictions above */
Version = ident | string .    /* see restrictions above */

go directive

​ 在一个有效的go.work文件中需要一个go指令。版本必须是有效的Go发布版本:一个正整数后跟一个点和一个非负整数(例如,1.181.19)。

go指令表示go.work文件所要使用的go工具链版本。如果go.work文件的格式发生了变化,未来版本的工具链将根据其指示的版本来解释该文件。

​ 一个go.work文件最多只能包含一个go指令。

GoDirective = "go" GoVersion newline .
GoVersion = string | ident .  /* valid release version; see above */

示例:

go 1.18

use directive

use将磁盘上的一个模块添加到工作区的主模块集合中。它的参数是包含该模块的go.mod文件的目录的相对路径。use指令并不添加包含在其参数目录下的子目录中的模块。这些模块可以由包含其go.mod文件的目录在单独的use指令中添加。=>仍有疑问??这里应该是"require指令中添加吧"??

UseDirective = "use" ( UseSpec | "(" newline { UseSpec } ")" newline ) .
UseSpec = FilePath newline .
FilePath = /* platform-specific relative or absolute file path */

示例:

use ./mymod  // example.com/mymod

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

replace directive

​ 与go.mod文件中的replace指令类似,go.work文件中的replace指令用其他地方的内容替换一个模块的特定版本,或一个模块的所有版本。go.work中的通配符替换可以覆盖go.mod文件中特定版本的replace

go.work文件中的replace指令会覆盖工作区模块中相同模块或模块版本的任何替换。

ReplaceDirective = "replace" ( ReplaceSpec | "(" newline { ReplaceSpec } ")" newline ) .
ReplaceSpec = ModulePath [ Version ] "=>" FilePath newline
            | ModulePath [ Version ] "=>" ModulePath Version newline .
FilePath = /* platform-specific relative or absolute file path */

示例:

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
)