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

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

介绍

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

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

引言

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

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

使用方式

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

创建 Go 项目

# 进入 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

示例代码:

package main
import (
 "fmt"
 "golang.org/x/example/stringutil"
)
func main() {
 str := "hello"
 reverseStr := stringutil.Reverse(str)
 fmt.Println(reverseStr)
}

输出结果:

go run main.go
olleh

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

创建工作区

# 进入 Home 目录下的 workspace 目录
cd ~/workspace
# 初始化工作区
go work init ./hello

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

go 1.19
use ./hello

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

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

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

cd ~/workspace
go run hello/main.go

输出结果:

olleh

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

cd ~
go run workspace/hello/main.go

输出结果:

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 模式时,我们需要下载依赖项到本地,然后修改下载到本地的依赖项文件。

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

func ToUpper(s string) string {
 r := []rune(s)
 for i := range r {
  r[i] = unicode.ToUpper(r[i])
 }
 return string(r)
}

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

...
toUpperStr := stringutil.ToUpper(str)
fmt.Println(toUpperStr)
...

输出结果:

cd ~/workspace/hello
go run main.go
HELLO

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

使用 Workspaces 模式

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

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

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


目录
相关文章
|
3月前
|
缓存 NoSQL Go
通过 SingleFlight 模式学习 Go 并发编程
通过 SingleFlight 模式学习 Go 并发编程
|
6天前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
27天前
|
安全 Go 调度
探索Go语言的并发模式:协程与通道的协同作用
Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
|
27天前
|
安全 Go 开发者
破译Go语言中的并发模式:从入门到精通
在这篇技术性文章中,我们将跳过常规的摘要模式,直接带你进入Go语言的并发世界。你将不会看到枯燥的介绍,而是一段代码的旅程,从Go的并发基础构建块(goroutine和channel)开始,到高级模式的实践应用,我们共同探索如何高效地使用Go来处理并发任务。准备好,让Go带你飞。
|
3月前
|
存储 Unix 测试技术
解释Go中常见的I/O模式
解释Go中常见的I/O模式
|
3月前
|
算法 搜索推荐 Unix
快速指南: Go 1.19功能
快速指南: Go 1.19功能
|
3月前
|
编译器 Go
Go语言中的闭包:封装数据与功能的强大工具
Go语言中的闭包:封装数据与功能的强大工具
|
3月前
|
缓存 算法 Go
|
3月前
|
存储 Unix 测试技术
解释Go中常见的I/O模式
解释Go中常见的I/O模式