Go workspace的使用

2024-02-27 11:22:18 浏览数 (1)

引入背景

Go Workspace[1]和泛型,模糊测试一样, 也是Go语言在1.18版本中引入的一个新特性,目的是为了解决在开发涉及多个模块(module)的Go项目时的依赖管理问题。

在引入Workspace之前,当项目被拆分成多个模块进行管理时,依赖于本地模块的管理可能会变得复杂。特别是在本地开发环境中,开发者需要频繁地使用replace指令在go.mod文件中手动指定模块的本地路径,以便在不发布到远程仓库的情况下引用本地模块。这种方法虽然可行,但对于涉及多个模块的大型项目来说,维护成本较高,而且容易出错。

即对于较大的项目,一般会抽离出一个或多个公用组件(往往叫做go-base,go-common). 当开发这个公共组件库时,不太方便push到远程仓库,再通过go get等拉取到本地(因为多人共用这个库), 之前的办法是在go.mod中增加一个或多个replace块.

而Workspace的引入旨在简化和优化这一流程,使得开发者能够更方便地在本地环境中管理和编译涉及多个模块的项目,而无需修改go.mod文件或使用多个replace指令。

之前用replace的方式

假设项目抽离出了两个模块:commonserviceservice模块对外提供服务, 其依赖于common模块。在没有Workspace功能之前,如果common模块在本地进行了修改,service模块需要通过replace指令在其go.mod文件中指定common模块的本地路径来引用这些更改,从而进行调试.

代码语言:javascript复制
mkdir workspace-demo
cd workspace-demo

mkdir common
cd common
code utils.go
go mod init dashen.tech/common

mkdir service
cd service
code main.go
go mod init dashen.tech/service
code go.mod

其中utils.go:

代码语言:javascript复制
package utils

import "math/rand"

func GenerateOrderID() string {
 return "order-"   randomString(10)
}

func randomString(n int) string {
 b := make([]byte, n)
 for i := range b {
  b[i] = byte(65   rand.Intn(26)) // A = 65, Z = 90
 }
 return string(b)
}

修改service/go.mod为:

代码语言:javascript复制
module dashen.tech/service

go 1.21rc2

require dashen.tech/common v0.0.0-incompatible // 引入这个包

replace dashen.tech/common => ../common // 将此包指向本地目录的路径

replace的作用很多,可以

  • 替换无法下载的包
  • 调试依赖包(或引用本地包)
  • 使用fork的仓库
  • 禁止被依赖

此处仅用到了引用本地包的功能

更多可参考:

  • 【Go mod 学习之 replace 篇】解决 go 本地依赖、无法拉取依赖、禁止依赖等问题[2]
  • go mod替换本地包[3]

main.go:

代码语言:javascript复制
package main

import (
 "fmt"

 utils "dashen.tech/common"
)

func main() {

 fmt.Println(utils.GenerateOrderID())

}

执行go run main.go,输出:

IDE可能会有错误提示,忽略即可

使用workspace方式

使用Go Workspace方式也非常简单,主要有以下几个步骤:

  1. 初始化Workspace: 在项目的根目录下,使用go work init命令初始化一个新的Workspace。这将创建一个go.work文件。
  2. 添加模块到Workspace: 通过go work use命令,可以将一个或多个模块的路径添加到Workspace中。这样做可以告诉Go工具链在构建和测试时考虑这些模块。
  3. 构建和测试: 在Workspace环境中,可以像平常一样使用go buildgo test等命令,Go工具链会自动解析Workspace中的模块依赖关系。

清空service/go.mod中的require和replace信息

代码语言:javascript复制

cd workspace-demo
go work init
go work use ./service 
go work use ./common

此时会新生成一个go.work文件,内容为如下:

无需修改main.go, 直接执行go run main.go, 可输出预期结果

不仅仅是go run, 在项目目录下运行go buildgo test命令时,Go工具链也会自动识别这两个模块之间的依赖关系,通过Go Workspace这种方式,一定程度上简化了涉及多个模块的项目的本地开发和测试流程,提高了开发效率。

(我感觉只是比之前replace的方式优雅了一点点,效率其实大差不差)

另外,go.work需要加入到.gitignore中,不要提交到仓库.

参考资料

[1]

Go Workspace: https://go.dev/doc/tutorial/workspaces

[2]

【Go mod 学习之 replace 篇】解决 go 本地依赖、无法拉取依赖、禁止依赖等问题: https://blog.csdn.net/qq_24433609/article/details/127323097

[3]

go mod替换本地包: https://blog.csdn.net/weixin_49702653/article/details/124340992

0 人点赞