Go 1.18 新增三大功能之一“工作区模式”介绍

2022-12-27 16:07:43 浏览数 (1)

01

介绍

Go 官方在 Go v1.11 新增 Go Modules 模式,并一直持续到 Go v1.16,每个版本的 Go Modules 模式都会有一些变化。但是,我们的项目使用 Go Modules 模式时,仍然会遇到一些问题。

直到 Go v1.18 版本新增 Workspaces 模式,解决了 Go Modules 模式的这些问题,本文我们介绍 Workspaces 模式的使用方式。

02

引言

当在项目中需要导入一些私有 Git 仓库或未发布到 Git 仓库的依赖项时,或需要修改三方依赖模块的代码时,一般解决方法是将代码下载到本地,在 go.mod 文件中使用 Go Modules 模式中的 replace 指令替换为本地目录路径。

因为 go.mod 文件也是和项目一起提交到 Git 仓库,每个开发人员的本地目录路径可能不一样,所以,就需要把在远程仓库拉取到的 go.mod 文件中 replace 的目录路径手动替换为自己的本地目录路径之后,才可以正常使用。

03

使用方式

在介绍 Workspaces 模式的使用方式之前,我们需要先使用 Go Modules 模式创建一个 Go 项目,并且我们的 Go 项目依赖模块 golang.org/x/example

创建 Go 项目

代码语言:javascript复制
# 进入 Home 目录
cd ~
# 创建工作区目录
mkdir workspace
# 进入工作区目录
cd workspace
# 创建 Go 项目所在的目录
mkdir hello
# 进入 Go 项目所在的目录
cd hello
# 初始化
go mod init github.com/weirubo/hello
# 添加依赖项
go get golang.org/x/example
# 创建 main.go 文件
touch main.go

示例代码:

代码语言:javascript复制
package main

import (
 "fmt"
 "golang.org/x/example/stringutil"
)

func main() {
 str := "hello"
 reverseStr := stringutil.Reverse(str)
 fmt.Println(reverseStr)
}

输出结果:

代码语言:javascript复制
go run main.go
olleh

阅读上面这段内容,是我们已经非常熟悉的使用 Go Modules 模式创建 Go 项目的操作步骤,接下来,我们介绍 Workspaces 模式的使用方式。

创建工作区

代码语言:javascript复制
# 进入 Home 目录下的 workspace 目录
cd ~/workspace
# 初始化工作区
go work init ./hello

执行完以上命令,我们可以发现在 workspace 目录下创建了一个 go.work 文件,查看该文件,我们可以发现包含两个指令,分别是 gouse

代码语言:javascript复制
go 1.19

use ./hello

其中 go 指令,是指定使用 Go 的哪个版本编译项目,类似 go.mod 文件中的 go 指令。

其中 use 指令,是指在构建项目时,hello 目录中的模块是主模块。

在创建工作区后,我们进入工作区目录,运行 main.go 文件。

代码语言:javascript复制
cd ~/workspace
go run hello/main.go

输出结果:

代码语言:javascript复制
olleh

但是,如果我们进入 Home 目录(工作区外),运行 main.go 文件。

代码语言:javascript复制
cd ~
go run workspace/hello/main.go

输出结果:

代码语言:javascript复制
workspace/hello/main.go:5:2: no required module provides package golang.org/x/example/stringutil: go.mod file not found in current directory or any parent directory; see 'go help modules'

我们可以在输出结果中发现,Go 找不到项目使用的依赖模块,原因是我们在工作区外运行 Go 项目,Go 找不到需要的模块。

04

使用场景

我们在学会使用 Workspaces 模式后,使用该模式解决 Part 02 提到的问题。

假如我们想要在 Go 项目的依赖模块 golang.org/x/example 新增一个函数 ToUpper

在 Go 未提供 Workspaces 模式时,我们需要下载依赖项到本地,然后修改下载到本地的依赖项文件。

代码语言:javascript复制
cd ~/workspace/hello
git clone https://go.googlesource.com/example
# 编辑 go.mod
go mod edit -replace golang.org/x/example@v0.0.0-20220412213650-2e68773dfca0=/Users/frank/workspace/hello/example

此时,我们就可以修改我们下载到本地的依赖项文件 /Users/frank/workspace/hello/example/stringutil/reverse.go,新增函数 ToUpper

代码语言:javascript复制
func ToUpper(s string) string {
 r := []rune(s)
 for i := range r {
  r[i] = unicode.ToUpper(r[i])
 }
 return string(r)
}

然后,我们可以在 main.go 文件中使用该函数。

代码语言:javascript复制
...
toUpperStr := stringutil.ToUpper(str)
fmt.Println(toUpperStr)
...

输出结果:

代码语言:javascript复制
cd ~/workspace/hello
go run main.go
HELLO

使用 Go Modules 模式的 replace 指令,虽然可以实现我们的需求,但是,当该项目代码在其他人电脑上运行时,必须先手动修改为自己的目录路径,才可以正常运行。

使用 Workspaces 模式

我们使用 Go 1.18 提供的 Workspaces 模式,实现我们的需求。

将下载到本地的依赖模块 example 添加到工作区:

代码语言:javascript复制
cd ~/workspace
go work use ./hello/example

我们使用 go work use 命令将 example 模块添加到工作区,我们就可以使用我们下载到本地的依赖模块 example 的代码,而不再使用 GOMODCACHE 中的 example 模块的代码。

我们项目组成员只需维护自己本地的工作区,不必再手动修改 go.mod 文件中 replace 指令中的本地目录路径。

05

总结

本文我们先叙述使用 Go Modules 模式面临的一些问题,然后介绍 Go v1.18 新增的 Workspaces 模式的使用方式,最后通过示例介绍使用 Workspaces 模式可以解决使用 Go Modules 模式中的问题。

需要注意的是,go.work 文件不要推送到远程仓库,我们可以将其添加到 .gitignore 文件中。

我们在文中使用到的命令是 go work initgo work use,此外,还有其他命令,感兴趣的读者朋友们可以执行命令 go help work 了解更多。

参考资料:

  1. https://github.com/golang/proposal/blob/master/design/45713-workspace.md
  2. https://www.youtube.com/watch?v=wQglU5aB5NQ
  3. https://go.dev/blog/get-familiar-with-workspaces
  4. https://go.dev/doc/tutorial/workspaces
  5. https://go.dev/ref/mod#workspaces
  6. https://pkg.go.dev/cmd/go#hdr-Workspace_maintenance
  7. https://go.dev/ref/mod#commands-outside

0 人点赞