• Go工作空间


    摘要:工作空间是Go 1.18新添加的特性,英文名叫workspace,同时还有和工作空间相关的命令go work。工作空间与Go模块是完全不同的概念。模块是代码组织的一种方式,工作空间本质上是一个目录,它影响的是编译器的工作,只在开发人员的本地发挥作用。工作空间的出现是为了方便多模块开发模式,本文将会介绍任何使用工作空间进行开发。


    Go Module的开发模式

    从Go1.11开始,Go Module横空出世,让我们摆脱了Go Path,从此代码可以放在任意地方。虽然饱受争议,但也在磕磕盼盼中逐渐被人们接受。由于Go工作空间并不是Go Module的替代之物,所以还是让我们从Go Module开始吧。

    首先找一个地方,打开PowerShell,然后依次执行以下命令。

    mkdir work
    cd work
    mkdir hello
    mkdir world
    cd hello
    go mod init github.com/caiwangg/hello
    new-item hello.go
    cd ../world
    go mod init github.com/caiwangg/world
    new-item world.go
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    其实,上面的命令做了这样一件事:创建一个work文件夹,进入work文件夹创建helloworld两个目录。然后分别在两个目录中初始化Go模块,并分别在两个目录中创建hello.goworld.go文件。

    这就是一个简单的多模块开发场景,在工作中也很常见,比如我们可能需要同时开发主项目和公共的工具库。作为例子,我们只是模仿这一形式。

    接下来用你喜欢的代码编辑器打开hello.go,输入以下代码。

    package hello
    
    func SayHello(name string) string {
    	return "Hello, " + name + " !"
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    同样,在world.go中输入以下代码。

    package main
    
    import (
    	"fmt"
    
    	"github.com/caiwangg/hello"
    )
    
    func main() {
    	name := "Caiwangg"
    	fmt.Println(hello.SayHello(name))
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    为了在world中能够调用hello模块的函数,我们还需要修改一下world模块中的go.mod文件,在文件最后添加以下两行内容。

    require github.com/caiwangg/hello v0.1.0
    
    replace github.com/caiwangg/hello v0.1.0 => ../hello
    
    • 1
    • 2
    • 3

    现在切换到world目录下,执行以下命令运行项目。

    PS XXX\work\world> go run .
    Hello, Caiwangg !
    
    • 1
    • 2

    看到Hello, Caiwangg !的输出说明我们的项目是正常的。但是这其中有一个小小的问题,我们的代码不可能永远放在本地,不管是hello模块还是world模块,它们都有对应的代码仓库,尽管我们的例子中没有显示出这一点。

    为了使用本地正在开发的hello模块,我们不得不在world模块的go.mod文件中使用replace指令。当我们要将world模块推送到代码仓库时,又必须把replace去掉。频繁的修改go.mod文件对我们来说将是一个麻烦。

    Go工作空间

    我们在上一节中创建的work目录就是为工作空间做准备的。首先我们在powershell中切换到work目录,然后执行以下命令:

    go work init world hello
    
    • 1

    以上命令用来初始化工作空间,它会在work目录下创建一个go.work文件,命令中的worldhello都会出现在go.work文件的use模块中。以下就是我们的go.work文件的内容。

    go 1.18
    
    use (
    	./hello
    	./world
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    该命令的基本语法是go work init [moddirs],如果不提供moddirs,将会创建一个空的工作空间。工作空间声明了一组模块,同一个工作空间中的模块互相可见,可以直接使用。

    工作空间创建以后,还可以通过go work use [-r] moddirs添加模块,-r表示递归子目录。当然你也可以直接在代码编辑器中编辑go.work文件。

    现在,我们把之前在worldgo.mod文件中添加的那两行去掉,也就是将它恢复成如下样子。

    module github.com/caiwangg/world
    
    go 1.18
    
    // require github.com/caiwangg/hello v0.1.0
    
    // replace github.com/caiwangg/hello v0.1.0 => ../hello
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    理论上来说,这时在work目录下运行go run .\world是编译不过的,因为找不到hello模块。但是由于go.work的存在,神奇的事情发生了,代码成功编译并运行,输出了Hello, Caiwangg !

    这就是工作空间的魅力,我们不需要replace指令,也不需要在提交代码时修改go.mod文件。编译器会自动使用工作空间下的模块,对于多模块同时开发的场景,这简直就是福音。也许在一开始你认为不会多线作战,但是公共模块这个东西往往都是在项目开发过程中被拆分出去的,因为项目架构也是随着开发在变化的。当你在项目开发的中途想拆分模块时,工作空间会让拆分过程更加丝滑无痛。

    总结

    总结个屁,冲就完了。


    附录

    Tutorial: Getting started with multi-module workspaces

  • 相关阅读:
    部署elasticsearch需要调整的系统参数
    从Unix看文言文为什么短
    3.7.2、IP地址(网际层)
    pyinstaller打包包含celery任务的项目总是失败解决方式
    Java中如何优雅的处理异常
    【LeetCode周赛】LeetCode第364场周赛
    C/C++ 运用WMI接口查询系统信息
    R语言使用scale函数对神经网络的输入数据进行最小最大缩放、把数据缩放到0到1之间、并划分数据集为训练集和测试集
    [WSL][ubuntu][原创]windows上ssh WSL的linux子系统
    基于springboot财务管理系统
  • 原文地址:https://blog.csdn.net/puss0/article/details/127604049