golang - 多模块工作区(multi-module workspaces)

go的多模块工作区是从1.18 版本开始的,所以要使用它首先要确认go 的版本。

$go version
go version go1.18 windows/amd64

一下教程介绍了一个多模块工作区的用例。在多模块工作区中创建两个模块,对这些模块进行更改,并在构建中查看这些更改的结果:

1. 创建项目

创建一个名为workspace 的目录,作为本次案例多模块的家目录

$ mkdir workspace

2. 创建项目
  • 进入工作区目录如下指令创建一个目录作为hello 的项目,并通过go mo初始化
    $ cd workspace
    $ mkdir hello
    $ cd hello
    $ go mod init example.com/hello
    go: creating new go.mod: module example.com/hello
    
  • 在该项目下,创建hello.go 文件,并创建如下main 函数, 并通过go mod tidy 命令 同步第三方依赖包
    package main
    
    import (
      "fmt"
      "golang.org/x/example/stringutil"
    )
    
    func main() {
      fmt.Println(stringutil.Reverse("Hello"))
    }
    
    
3. 创建工作区
  • 创建一个 go.work 文件来指定带有模块的工作区,在工作目录中(workspace 目录),指令如下:
    // go work init [路径]
    $ go work init ./hello
    

go work init 命令告诉 go 为包含 ./hello 目录中的模块的工作空间创建一个 go.work 文件。 go 命令生成一个如下所示的 go.work 文件:

    go 1.18

    use ./hello

go.work 文件的语法与 go.mod 相似。 go 指令告诉 Go 应该使用哪个版本的 Go 来解释文件。它类似于 go.mod 文件中的 go 指令。 use 指令告诉 Go 在构建时, hello 目录中的模块应该是主模块。 因此,在工作区的任何子目录中,该模块都将处于活动状态
在workspace目录中,运行hello 模块,此时可以正常运行

$ go run example.com/hello
olleH

工作区中的所有模块和go 命令都会被作为作为主模块。这允许我们在模块中引用一个包,甚至在该包在模块之外。在模块或工作区之外运行 go run 命令会导致错误,因为 go 命令不知道要使用哪些模块。 接下来,我们将 golang.org/x/example 模块的本地副本添加到工作区。然后,我们将向 stringutil 包添加一个新函数,我们可以使用它来代替 Reverse。

  • 克隆golang.org/x/example
    在工作区运行如下指令来克隆example代码
$ git clone https://go.googlesource.com/example
Cloning into 'example'...
remote: Total 165 (delta 27), reused 165 (delta 27)
Receiving objects: 100% (165/165), 434.18 KiB | 1022.00 KiB/s, done.
Resolving deltas: 100% (27/27), done.

通过如下指令将克隆的example 项目添加到工作目录中

go work use ./example

此时查看go.work 文件如下所示

go 1.18

use (
    ./example
    ./hello
)

该模块现在包括 example.com/hello 模块和 golang.org/x/example 模块。 这将允许我们使用我们将在 stringutil 模块的副本中编写的新代码,而不是使用 go get 命令下载的模块缓存中的模块版本.此时example和hello 模块相当于是本地私有模块,可以任意修改

  • 修改example 目录中代码
    我们将在 golang.org/x/example/stringutil 包中添加一个将字符串大写的新函数。 在 workspace/example/stringutil 目录中创建一个名为 toupper.go 的新文件,其中包含以下内容
package stringutil

import "unicode"

// ToUpper uppercases all the runes in its argument string.
func ToUpper(s string) string {
    r := []rune(s)
    for i := range r {
        r[i] = unicode.ToUpper(r[i])
    }
    return string(r)
}
  • 修改对应hello模块
    修改hello模块中对字符串反转的函数为新的ToUpper 函数(上面新添加的函数)
package main

import (
    "fmt"

    "golang.org/x/example/stringutil"
)

func main() {
    fmt.Println(stringutil.ToUpper("Hello"))
  • 运行hello模块
$ go run example.com/hello
HELLO

Go 命令在 go.work 文件指定的hello 目录中找到命令行中指定的example.com/hello 模块,并使用类似的方法解析golang.org/x/example 导入go.work 文件。 可以使用 go.work 而不是添加 replace 指令来跨多个模块工作。 由于这两个模块位于同一个工作区中,因此很容易在一个模块中进行更改并在另一个模块中使用它。

4 指令集
  1. go work init
    用法go work init [moddirs]
    在当前目录中初始化并写入一个新的 go.work 文件,实际上是在当前目录中创建了一个新的工作空间。 go work init 可选择接受工作区模块的路径作为参数。如果省略该参数,将创建一个没有模块的空工作区。 每个参数路径都添加到 go.work 文件中的 use 指令中。当前的 go 版本也将列在 go.work 文件中。
    利润上面例子中,通过 go mod init ./hello 指令在workspace 目录下,创建了一个go.work 文件,并将hello 模块路径添加到go.work 中,具体内容如下:
    go 1.18

    use ./hello
  1. go work edit
    用法go work edit [editing flags] [go.work]
    go work edit 命令提供了一个用于编辑 go.work 的命令行接口,主要供工具或脚本使用。它只读取 go.work;不查找有关所涉及模块的信息。如果没有指定文件,Edit 在当前目录及其父目录中查找 go.work 文件

    editing flags

    • fmt:
      fmt 标志重新格式化 go.work 文件而不进行其他更改, 此标志只能单独使用,不能和其他标志同时使用,
      示例:go work edit -fmt

    • replace:
      -replace=old[@v]=new[@v] 指定模块的新模块与旧模块的替代, 其中版本号(@v)可以被省略。如果旧模块中的版本号(@v)被省略了, 相当于指定了旧模块的所有版本; 如果新模块中的版本号(@v)被省略了,则新模块的路径应该是本地模块根目录,而不是模块路径

    • dropuse:
      从 go.work 文件的模块目录集中删除一个 use 指令, 用法go work edit -dropuse=待删除模块的路径

    • dropreplace:
      删除给定模块路径和版本对的替换

    • go:
      设置go.work 文件中的go 语言版本,go work edit -go=1.18

  1. go work use
    用法go work use [-r] [moddirs]

go work use 命令提供了一个命令行接口,用于将模块目录(-r: 可以选择以递归方式)添加到 go.work 文件中。
-r: 标志递归搜索参数目录中的模块

  1. go work sync
    用法go work sync
    go work sync 命令将工作区的构建列表同步回工作区的模块
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容