查看原文
其他

Go1.18 快讯:这个新特性太实用了

站长polaris polarisxu 2022-11-21

阅读本文大概需要 5 分钟。

大家好,我是 polarisxu。

工作区模式(Workspace mode),可不是之前 GOPATH 时代的 Workspace,而是希望在本地开发时支持多 Module。

01 缘起

为了大家全面理解工作区模式,通过一个具体例子讲解。

本地有两个项目,分别是两个 module:mypkg 和 example。(Windows 系统请按自己方式创建目录)

cd ~/
$ mkdir polarisxu
cd polarisxu
$ mkdir mypkg example
cd mypkg
$ go mod init github.com/polaris1119/mypkg
$ touch bar.go

在 bar.go 中增加如下示例代码:

package mypkg

func Bar() {
 println("This is package mypkg")
}

接着,在 example 模块中处理:

cd ~/polarisxu/example
$ go mod init github.com/polaris1119/example
$ touch main.go

在 main.go 中增加如下内容:

package main

import (
    "github.com/polaris1119/mypkg"
)

func main() {
    mypkg.Bar()
}

这时候,如果我们运行 go mod tidy,肯定会报错,因为我们的 mypkg 包根本没有提交到 github 上,肯定找不到。

fatal: repository 'https://github.com/polaris1119/mypkg/' not found

go run main.go 也就不成功。

我们当然可以提交 mypkg 到 github,但我们每修改一次 mypkg,就需要提交,否则 example 中就没法使用上最新的。

针对这种情况,目前是建议通过 replace 来解决,即在 example 中的 go.mod 增加如下 replace:(v1.0.0 根据具体情况修改,还未提交,可以使用 v1.0.0)

module github.com/polaris1119/example

go 1.17

require github.com/polaris1119/mypkg v1.0.0

replace github.com/polaris1119/mypkg => ../mypkg

再次运行 go run main.go,输出如下:

$ go run main.go
This is package mypkg

当都开发完成时,我们需要手动删除 replace,并执行 go mod tidy 后提交,否则别人使用就报错了。

这还是挺不方便的,如果本地有多个 module,每一个都得这么处理。

02 工作区模式

针对上面的这个问题,Michael Matloob 提出了 Workspace Mode(工作区模式)。相关 issue 讨论:cmd/go: add a workspace mode[1]这里是 Proposal[2]

为了能够试验工作区,请在本地使用 gotip,建议通过 goup 切换 Go 版本

$ goup install tip
$ goup show
|  VERSION  | ACTIVE |
|-----------|--------|
|   1.0.1   |        |
|    1.1    |        |
|  1.10.8   |        |
|  1.14.9   |        |
|  1.15.2   |        |
|  1.15.3   |        |
|  1.15.4   |        |
|   1.16    |        |
|  1.16.2   |        |
| 1.16beta1 |        |
|   1.17    |        |
| 1.17beta1 |        |
|    1.4    |        |
|   1.4.3   |        |
|    tip    |   *    |

我本地当前 tip 版本:

$ go version
go version devel go1.18-c78a267bd4 Sat Nov 13 01:39:23 2021 +0000 darwin/amd64

通过 go help work 可以看到 work 相关命令:

Go workspace provides access to operations on worskpaces.

Note that support for workspaces is built into many other commands,
not just 'go work'.

See 'go help modules' for information about Go's module system of
which workspaces are a part.

Usage:

 go work <command> [arguments]

The commands are:

 edit        edit go.work from tools or scripts
 init        initialize workspace file
 sync        sync workspace build list to modules
 use         add modules to workspace file

Use "go help work <command>" for more information about a command.

根据这个提示,我们初始化 workspace:

cd ~/polarisxu
$ go work init mypkg example
$ tree
.
├── example
│   ├── go.mod
│   └── main.go
├── go.work
└── mypkg
    ├── bar.go
    └── go.mod

注意几点:

  • 多个子模块应该在一个目录下。比如这里的 polarisxu 目录;(这不是必须的,但更好管理,否则 go work init 需要提供正确的子模块路径)
  • go work init 需要在 polarisxu 目录执行;
  • go work init 之后跟上需要本地开发的子模块目录名;

打开 go.work 看看长什么样:

go 1.18

directory (
    ./example
    ./mypkg
)

go.work 文件的语法和 go.mod 类似,因此也支持 replace。

现在,我们将 example/go.mod 中的 replace 语句删除,再次执行 go run main.go(在 example 目录下),得到了正常的输出。也可以在 polarisxu 目录下,这么运行:go run example/main.go,也能正常。

注意,go.work 不需要提交到 Git 中,因为它只是你本地开发使用的。

如果想要禁用 workspace,可以通过 -workfile=off 实现。

-workfile file
  in module aware mode, use the given go.work file as a workspace file.
  By default or when -workfile is "auto", the go command searches for a
  file named go.work in the current directory and then containing directories
  until one is found. If a valid go.work file is found, the modules
  specified will collectively be used as the main modules. If -workfile
  is "off", or a go.work file is not found in "auto" mode, workspace
  mode is disabled.

比如:go run -workfile=off main.go 或 go build -workfile=off,这样运行你会发现又报错了。但通过这种方式,你可以验证依赖包提交到 github 上之后的情况。

03 总结

在 GOPATH 年代,多 GOPATH 是一个头疼的问题。当时没有很好的解决,Module 就出现了,多 GOPATH 问题因此消失。但多 Module 问题随之出现。Workspace 方案较好的解决了这个问题。

下篇文章,我会进一步讲解,如何在 VSCode 中试验 Workspace。

参考资料

[1]

cmd/go: add a workspace mode: https://github.com/golang/go/issues/45713

[2]

这里是 Proposal: https://go.googlesource.com/proposal/+/master/design/45713-workspace.md




往期推荐


我是 polarisxu,北大硕士毕业,曾在 360 等知名互联网公司工作,10多年技术研发与架构经验!2012 年接触 Go 语言并创建了 Go 语言中文网!著有《Go语言编程之旅》、开源图书《Go语言标准库》等。


坚持输出技术(包括 Go、Rust 等技术)、职场心得和创业感悟!欢迎关注「polarisxu」一起成长!也欢迎加我微信好友交流:gopherstudio


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存