关于golang:Go-118工作区模式workspace-mode

8次阅读

共计 3234 个字符,预计需要花费 9 分钟才能阅读完成。

背景

Go 1.18 除了引入泛型 (generics)、含糊测试(Fuzzing) 之外,另外一个重大性能是引入了工作区模式(workspace mode)。

工作区模式对 本地同时开发多个有依赖的 Module的场景十分有用。

举个例子,咱们当初有 2 个 Go module 我的项目处于开发阶段,其中一个是 example.com/main,另外一个是example.com/util。其中example.com/main 这个 module 须要应用 example.com/util 这个 module 里的函数。

咱们来看看 Go 1.18 版本前后如何解决这种场景。

Go 1.18 之前怎么做

在 Go 1.18 之前,对于上述场景有 2 个解决计划:

计划 1:被依赖的模块及时提交代码到代码仓库

这个计划很好了解,既然 example.com/main 这个 module 依赖了 example.com/util 这个 module,那为了 example.com/main 能应用到 example.com/util 的最新代码,须要做 2 个事件

  • 本地开发过程中,如果 example.com/util 有批改,都马上提交代码到代码仓库,而后打 tag
  • 紧接着 example.com/main 更新依赖的 example.com/util 的版本号 (tag),能够应用go get -u 命令。

这种计划比拟繁琐,每次 example.com/util 有批改,都要提交代码,否则 example.com/main 这个 module 就无奈应用到最新的example.com/util

计划 2:go.mod 里应用 replace 指令

为了解决方案 1 的痛点,于是有了计划 2:在 go.mod 里应用 replace 指令。

通过 replace 指令,咱们能够间接应用 example.com/util 这个 module 的本地最新代码,而不必把 example.com/util 的代码提交到代码仓库。

为了不便大家了解,咱们间接上代码。代码目录构造如下:

module
|
|------main
|        |---main.go
|        |---go.mod        
|------util
|        |---util.go
|        |---go.mod

main 目录下的 main.go 代码如下:

//main.go
package main

import (
    "fmt"

    "example.com/util"
)

func main() {result := util.Add(1, 2)
    fmt.Println(result)
}

main 目录下的 go.mod 内容如下:

module example.com/main

go 1.16

require example.com/util v1.0.0

replace example.com/util => ../util

util 目录下的 util.go 代码如下:

// util.go
package util

func Add(a int, b int) int {return a + b}

util 目录下的 go.mod 内容如下:

module example.com/util

go 1.16

这里最外围的是 example.com/main 这个 module 的go.mod,最初一行应用了 replace 指令。

module example.com/main

go 1.16

require example.com/util v1.0.0

replace example.com/util => ../util

通过 replace 指令,应用 go 命令编译代码的时候,会找到本地的 util 目录,这样 example.com/main 就能够应用到本地最新的 example.com/util 代码。进入 main 目录,运行代码,后果如下所示:

$ cd main
$ go run main.go
3

然而这种计划也有个问题,咱们在提交 example.com/main 这个 module 的代码到代码仓库时,须要删除最初的 replace 指令,否则其余开发者下载后会编译报错,因为他们本地可能没有 util 目录,或者 util 目录的门路和你的不一样。

代码开源地址:Go 1.18 之前应用 replace 指令

Go 1.18 工作区模式

为了解决方案 2 的痛点,在 Go 1.18 里新增了工作区模式(workspace mode)。

该模式下不再须要在 go.mod 里应用 replace 指令,而是新增一个 go.work 文件。

话不多说,间接上代码。代码目录构造如下:

workspace
|------go.work
|
|------main
|        |---main.go
|        |---go.mod        
|------util
|        |---util.go
|        |---go.mod

main 目录下的 main.go 代码如下:

//main.go
package main

import (
    "fmt"

    "example.com/util"
)

func main() {result := util.Add(1, 2)
    fmt.Println(result)
}

main 目录下的 go.mod 内容如下:没有了计划 2 里最初一行的 replace 指令

module example.com/main

go 1.16

require example.com/util v1.0.0

util 目录下的 util.go 代码如下:

// util.go
package util

func Add(a int, b int) int {return a + b}

util 目录下的 go.mod 内容如下:

module example.com/util

go 1.16

go.work内容如下:

go 1.18

use (
    ./main
    ./util
)

在 workspace 目录下执行如下命令即可主动生成go.work

$ go1.18beta1 work init main util

go1.18beta1 work init前面跟的 mainutil都是 Module 对应的目录。

如果 go 命令执行的当前目录或者父目录有 go.work 文件,或者通过 GOWORK 环境变量指定了 go.work 的门路,那 go 命令就会进入工作区模式。在工作区模式下,go 就能够通过 go.work 下的 module 门路找到并应用本地的 module 代码。

在 main 目录或者 workspace 目录,都能够运行main.go,后果如下所示:

$ go1.18beta1 run main/main.go 
3
$ cd main/
$ go1.18beta1 run main.go
3

这种模式下,咱们对 example.com/main 没有任何本地侵入性批改,不必像计划 2 那样,提交代码前还须要更新go.mod 文件。example.com/main里的内容都能够间接提交到代码仓库。

代码开源地址:Go 1.18 工作区模式

留神 go.work 不须要提交到代码仓库中,仅限于本地开发应用。

总结

为了解决多个有依赖的 Module 本地同时开发的问题,Go 1.18 引入了工作区模式。

工作区模式是对已有的 Go Module 开发模式的优化,对于工作区模式的更多细节能够参考本文最初的 References。

开源地址

文章和示例代码开源在 GitHub: Go 语言高级、中级和高级教程。

公众号:coding 进阶。关注公众号能够获取最新 Go 面试题和技术栈。

集体网站:Jincheng’s Blog。

知乎:无忌。

References

  • Proposal 提案:https://go.googlesource.com/p…
  • workspace 官网教程:https://go.dev/doc/tutorial/w…
  • workspace 语法:https://go.dev/ref/mod#go-wor…
  • go work 命令手册:https://pkg.go.dev/cmd/go@mas…
  • go 1.18 release notes: https://tip.golang.org/doc/go…
  • Go 如何援用本地 Module:https://github.com/jincheng9/…
  • polarisxu: https://polarisxu.studygolang…
正文完
 0