当前位置: 首页 > news >正文

GO语言 | go work 神一般的管理 多个module没烦恼

文章目录

  • 前言
    • go work工作区模式
  • go work用法介绍
    • go work init
    • go work use
    • go.work
  • 使用场景和最佳实践
    • 使用场景1
    • 使用场景2
    • 使用场景3:切换依赖配置
  • 实战操作
    • 1 package name
    • 2 go mod init *
    • 3 go work init [path-to-module-one] [path-to-module-two]
    • 4 main调用

前言

最近手上有个活,需要自己本地包之间进行依赖

具体描述如下:

设计了如下目录结构,其中关注postman部分,要求核心程序放在internal文件目录,cmd目录存放一个cmd版本的main,wasm目录存放一个wasm版本的main,但cmd和wasm的main都依赖于internal目录下的程序实现。
在这里插入图片描述
有了目标,原理上很简单,找到办法实现cmd可以导入internal包的方法就可以了

但是,就这么一个听起来很简单的目标,用过Go的都知道,虽然mod实现了Go的存放位置自由,但并没有解决全部问题,上述简单的梦想实现起来又得是各种左右摇摆的一通操作

在经过了艰苦卓绝的寻找之后

https://cloud.tencent.com/developer/article/1998266

https://zhuanlan.zhihu.com/p/109828249

这两篇文章详细介绍了如何跨文件目录进行本地包的操作,但是无奈本人抄都能抄错,就是没有办法完美实现两个目录包的调用,实现不了我理想中的状态,并且整个过程可以说是罗里吧嗦,这不科学

无意间发现了go在1.18版本更新了一个超级重磅的功能,那就是work!
在这里插入图片描述

看完了官方的描述,我确信,这就是我要找的人,国际惯例,还是原文地址先贴一下,外文好的,可直接一手理解

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

go work工作区模式

Go 1.18引入的工作区模式,可以让你不用修改每个Go Module的go.mod,就能同时跨多个Go Module进行开发

工作区里的每个Go Module在解析依赖的时候都被当做根Module。

在Go 1.18以前,如果遇到以下场景:Module A新增了一个feature,Module B需要使用Module A的这个新feature,你有2种方案:

  • 发布Module A的修改到代码仓库,Module B更新依赖的Module A的版本即可
  • 修改Module B的go.mod,使用replace指令把对Module A的依赖指向你本地未发布的Module A所在目录。等Module A发布后,在发布Module B的时候,再删除Module B的go.mod文件里的replace指令。

有了Go工作区模式之后,针对上述场景,我们有了更为简单的方案:你可以在工作区目录维护一个go.work文件来管理你的所有依赖。go.work里的use和replace指令会覆盖工作区目录下的每个Go Module的go.mod文件,因此没有必要去修改Go Module的go.mod文件了。

go work用法介绍

go work init

使用go work init来创建一个workspace,go work init 的语法如下所示:

go work init [moddirs]

moddirs是Go Module所在的本地目录。如果有多个Go Module,就用空格分开。如果go work init后面没有参数,会创建一个空的workspace。

执行go work init后会生成一个go.work文件,go.work里列出了该workspace需要用到的Go Module所在的目录,workspace目录不需要包含你当前正在开发的Go Module代码。

go work use

如果要给workspace新增Go Module,可以使用如下命令:

go work use [-r] moddir

或者手动编辑go work文件。

如果带有-r参数,会递归查找-r后面的路径参数下的所有子目录,把所有包含go.mod文件的子目录都添加到go work文件中。

如果某个Go Module的目录已经被加到go.work里了,后面该目录没有go.mod文件了或者该目录被删除了,那对该目录再次执行go work use命令,该目录的use指令会从go.work文件里自动移除。(注意:自动移除要从Go 1.18正式版本才会生效,Go 1.18beta1版本有bug,自动删除不会生效)

go.work

go.work的语法和go.mod类似,包含如下3个指令:

  • go: go的版本,例如 go 1.18
  • use: 添加一个本地磁盘上的Go Module到workspace的主Module集合里。use后面的参数是go.mod文件所在目录相对于workspace目录的相对路径,例如use ./main。use指令不会添加指定目录的子目录下的Go Module到workspace的主Module集合里。
  • replace: 和go.mod里的 replace指令类似。go.work里的 replace指令可以替换某个Go Module的特定版本或者所有版本的内容。

使用场景和最佳实践

Workspace使用起来很灵活,接下来会介绍最常见的几种使用场景及其最佳实践。

使用场景1

给上游模块新增feature,然后在你的Module里使用这个新feature

为你的workspace(工作区)创建一个目录。Clone一份你要修改的上游模块的代码到本地。本地修改上游模块的代码,增加新的feature。
在workspace目录运行命令go work init [path-to-upstream-mod-dir]。为了使用上游模块的新feature,修改你自己的Go Module代码。
在workspace目录运行命令 go work use [path-to-your-module] 。go work use 命令会添加你的Go Module的路径到 go.work 文件里:

go 1.18

use (
./path-to-upstream-mod-dir
./path-to-your-module
)

运行和测试你的Go Module。发布上游模块的新feature。发布你自己的Go Module代码。

使用场景2

同一个代码仓库里有多个互相依赖的Go Module

当我们在同一个代码仓库里开发多个互相依赖的Go Module时,我们可以使用go.work,而不是在go.mod里使用replace指令。

为你的workspace(工作区)创建一个目录。

Clone仓库里的代码到你本地。代码存放的位置不一定要放在工作区目录下,因为你可以在go.work里使用use指令来指定Module的相对路径。在工作区目录运行 go work init [path-to-module-one] [path-to-module-two] 命令。

示例: 你正在开发 example.com/x/tools/groundhog 这个Module,该Module依赖 example.com/x/tools 下的其它Module。你Clone仓库里的代码到你本地,然后在工作区目录运行命令 go work init tools tools/groundhog
go.work 文件里的内容如下所示:

go 1.18

use (
./tools
./tools/groundhog
)

tools路径下其它Module的本地代码修改都会被 tools/groundhog 直接使用到。

使用场景3:切换依赖配置

如果要测试你开发的代码在不同的本地依赖配置下的场景,你有2种选择:

创建多个workspace,每个workspace使用各自的go.work文件,每个go.work里指定一个版本的路径。

创建一个workspace,在go.work里注释掉你不想要的use指令。

对于创建多个workspace的方案:

为每个workspace创建独立的目录。比如你开发的代码依赖了example.com/util这个Go Module,但是想测试example.com/util2个版本的区别,你可以创建2个workspace目录。
在各自的workspace目录运行 go work init 来初始化workspace。在各自的workspace目录运行 go work use [path-to-dependency]来添加依赖的Go Module特定版本的目录。在各自的workspace目录运行 go run [path-to-your-module] 来测试go.work里指定的依赖版本。

对于使用同一个workspace的方案,可以直接编辑go.work文件,修改use指令后面的目录地址即可。

实战操作

上述官网的搬运完毕,下面记录下我的操作

我的目录结构

|
|——————cmd
|      |
|      |——main.go
|
|——————internal
|      |
|      |——util.go
|      |——common.go
|	   |——*.go

cmd目录存放main.go函数,internal目录存放核心程序
在这里插入图片描述
在这里插入图片描述

1 package name

首先第一步的操作,需要统一internal目录下的package名称

这里将internal划分在名叫internal的package包里面,每个子文件都定义为

package postmaninternal

在这里插入图片描述

2 go mod init *

第二步,在internal目录下,创建mod文件,只需要创建即可,不需要一定要再执行go get

go mod init internal

运行命令,创建mod,名叫internal,这个internal是internal文件夹包的名称,也是与外界交流的名称

3 go work init [path-to-module-one] [path-to-module-two]

对internal目录的操作结束了,下面是cmd目录的操作

保险起见,cmd目录也进行一个go mod操作

go mod init postmancmd

生成一个mod,叫做postmancmd,名称其实无所谓。

接下来是正题,执行go work init

go work init ./ ./internal

创建并添加cmd目录和internal目录到go.work中,这里的internal指的是目录路径,通过…/internal路径找到mod文件,得到当前文件夹的package名字叫做internal

go 1.19

use (
	.
	../internal
)

可继续在go.work中添加包路径,也可通过指令添加

go work use  [-r] moddir

4 main调用

设置完成后,在main.go里面调用包即可通过如下方式

import (
	"postmaninternal"
)

import (
	postmaninternal "postmaninternal"
)

postmaninternal "postmaninternal"前面的postmaninternal其实是类似于全局变量,给"postmaninternal"包起个在当前文件内的别称,类似与一个局部变量或者结构体什么的,可有可无,看个人习惯
在这里插入图片描述

相关文章:

  • 【C语言】指针数组
  • 基于51单片机数字电压表仿真设计_数码管显示
  • 种草模式崛起!小红书KOL达人种草成推广热门方向!
  • Git Commit规范指北
  • 易观之星 | “2022年度用户推荐数字应用”投票通道开启
  • Flutter实战之go_router路由组件入门指南
  • Java--MybatisPlus Wrapper构造器;分页;MP代码生成器(四)
  • JS高级(数据类型,数据_变量_内存)
  • 分类模型评估的实际编码
  • 攻防世界WEB练习-mfw
  • 设计模式:设计模式概述
  • 你真的了解并查集?
  • 如何设计散列表(哈希表)
  • 基于Springboot+vue的体用用品销售商城网站 elementui
  • 【37. 线性DP】
  • Android框架之Volley
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • angular2开源库收集
  • CentOS6 编译安装 redis-3.2.3
  • const let
  • Django 博客开发教程 16 - 统计文章阅读量
  • express + mock 让前后台并行开发
  • HTTP 简介
  • JavaScript服务器推送技术之 WebSocket
  • jquery cookie
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • Vultr 教程目录
  • 分类模型——Logistics Regression
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 聊聊hikari连接池的leakDetectionThreshold
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 白色的风信子
  • mysql面试题分组并合并列
  • 函数计算新功能-----支持C#函数
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​渐进式Web应用PWA的未来
  • ![CDATA[ ]] 是什么东东
  • #!/usr/bin/python与#!/usr/bin/env python的区别
  • ###STL(标准模板库)
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (C语言)逆序输出字符串
  • (Forward) Music Player: From UI Proposal to Code
  • (备忘)Java Map 遍历
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (九)One-Wire总线-DS18B20
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (转)详解PHP处理密码的几种方式
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • ******IT公司面试题汇总+优秀技术博客汇总
  • ***原理与防范