- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
本文分享自华为云社区《一起看看 Go 1.18 新特性之多模块工作区模式》,作者:宇宙之一粟 。
2022年,Go 团队发布 Go 1.18 ,作为一个大的版本变动,Go 1.18 理所当然涵盖了许多的新功能、Go 团队也提到是 Go 语言发布以来做的最大的一次变动,并且性能改进很大。
其中一个功能,就是提供了一个多模块工作区的模式。官方博客说明如下:
该段文字的翻译:Go 模块几乎已被普遍采用,Go 用户在我们的年度调查报告中对 Go 模块给予非常高的满意度得分。在我们的 2021 年用户调查中,用户跨多个模块工作识别出不同的模块最常见的挑战。在 Go 1.18 中,我们使用新的 Go 工作区模式解决了这个问题,这使得使用多个模块变得简单。
Go 的依赖管理,或 Go Module,已经存在了好几年,但一直受到很多批评和改进。在 Go 1.18 推出多模块工作区模式——Multi-Module Workspaces,用以支持模块的多个工作空间,我们来看看到底有什么特别。
每天处理 Go 项目时,有两个经典问题特别无趣:
第一种场景: 例如,在一个 Go 项目中,我们会使用 replace 来解决一些本地依赖或自定义代码。我们将在 go.mod 文件中使用 replace 来执行此操作。
如下的代码:
replace golang.org/x/net => /Users/eddycjy/go/awesomeProject
这在链接本地开发时允许准确性。但是同时又会有问题:
第二种场景: 当你在做一个本地的 Go 项目时,你可能同时在做多个库(项目库、工具库、第三方库)。
看如下的代码:
package main
import (
"github.com/eddycjy/pkgutil"
)
func main() {
pkgutil.PrintFish()
}
如果此时运行 go run 或 go mod tidy,它将不起作用并且会失败。
将抛出如下错误。
fatal: repository 'https://github.com/eddycjy/pkgutil/' not found
此异常是因为库 http://github.com/eddycjy/pkgutil 在 GitHub 上不可用,因此无法拉取。
解决方案: 在 Go 1.18 之前,我们要么替换,要么直接上传到 Github,依赖将由 Go 工具链拉取。
很多用户对此提出质疑:Go 的所有依赖项都必须上传到 GitHub,并具有强绑定吗?
这对新人非常不友好。
经过社区多轮反馈,Michael Matloob 提出提案:Proposal: Multi-Module Workspaces in cmd/go,经过广泛讨论和实施,Go 1.18 正式实施。
新提案的核心概念之一是添加了 go work 工作空间概念,该概念针对 Go Module 依赖管理模型。
可以在本地项目的 go.work 文件中设置一系列依赖的模块本地路径,然后将路径下的模块组合成当前Go项目的工作空间,即 N 个 Go Modules into 1 Go Work,用工作空间具有最高的读取优先级。
我们可以通过 go help 看到这一点,如下所示。
$ go help work
Work provides access to operations on workspaces.
Note that support for workspaces is built into many other commands, not
just 'go work'.
See 'go help modules' for information about Go's module system of which
workspaces are a part.
See https://go.dev/ref/mod#workspaces for an in-depth reference on
workspaces.
See https://go.dev/doc/tutorial/workspaces for an introductory
tutorial on workspaces.
A workspace is specified by a go.work file that specifies a set of
module directories with the "use" directive. These modules are used as
root modules by the go command for builds and related operations. A
workspace that does not specify modules to be used cannot be used to do
builds from local modules.
go.work files are line-oriented. Each line holds a single directive,
made up of a keyword followed by arguments. For example:
go 1.18
use ../foo/bar
use ./baz
replace example.com/foo v1.2.3 => example.com/bar v1.4.5
The leading keyword can be factored out of adjacent lines to create a block,
like in Go imports.
use (
../foo/bar
./baz
)
The use directive specifies a module to be included in the workspace's
set of main modules. The argument to the use directive is the directory
containing the module's go.mod file.
The go directive specifies the version of Go the file was written at. It
is possible there may be future changes in the semantics of workspaces
that could be controlled by this version, but for now the version
specified has no effect.
The replace directive has the same syntax as the replace directive in a
go.mod file and takes precedence over replaces in go.mod files. It is
primarily intended to override conflicting replaces in different workspace
modules.
To determine whether the go command is operating in workspace mode, use
the "go env GOWORK" command. This will specify the workspace file being
used.
Usage:
go work <command> [arguments]
The commands are:
edit edit go.work from tools or scripts
init initialize workspace file
sync sync workspace build list to modules
use add modules to workspace file
Use "go help work <command>" for more information about a command.
只需执行 go work init 来初始化一个新的工作空间,然后是要生成的特定子模块 mod 的参数。
命令如下:
go work init ./mod ./tools
项目结构如下:
awesomeProject
├── mod
│ ├── go.mod // 子模块
│ └── main.go
├── go.work // 工作区
└── tools
├── fish.go
└── go.mod // 子模块
生成的 go.work 文件的内容如下:
go 1.18
use (
./mod
./tools
)
新的 go.work 与 go.mod 具有相同的语法,也可以与替换语法一起使用。
go 1.18
use (...)
replace golang.org/x/net => example.com/fork/net v1.4.5
go.work 文件中总共支持三个指令。
如果要禁用工作区模式,可以使用 -workfile=off 命令指定它。
即在运行时执行以下命令。
go run -workfile=off main.go
go build -workfile=off
go.work 文件不需要提交到 Git 存储库,否则有点折腾。
只要您在 Go 项目中设置了 go.work,您将在运行时和编译时处于工作区模式,并且工作区配置将被给予最高优先级以满足您的本地开发需求。
工作区的核心知识到此结束。
根据官方教程,我们来看一下如何使用多个工作区模式。
1、打开终端,进去 home 目录:
$ cd
$ mkdir workspace_test && cd workspace_test
2、module 初始化
创建一个依赖于 http://golang.org/x/example 模块的新模块 hello:
$ mkdir hello && cd hello
$ go mod init example.com/hello
go: creating new go.mod: module example.com/hello
3、使用 go get 添加对 http://golang.org/x/example 模块的依赖。
$ go get golang.org/x/example
go: downloading golang.org/x/example v0.0.0-20220304235025-ad95e7f791d8
go: added golang.org/x/example v0.0.0-20220304235025-ad95e7f791d8
4、在 hello 目录下创建 hello.go 文件,内容如下:
package main
import (
"fmt"
"golang.org/x/example/stringutil"
)
func main() {
fmt.Println(stringutil.Reverse("Hello, yuzhou1su"))
}
最后的代码结构如下:
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2af7a44539e948e396c965460fba4575~tplv-k3u1fbpfcp-zoom-1.image
运行这个 hello 程序,得到一个反转的字符串结果:
$ go run example.com/hello
us1uohzuy ,olleH
5、我们将创建一个 go.work 文件来指定带有模块的工作区。
首先,初始化工作区:
# wade @ wade-virtual-machine in ~/workspace_test [23:02:29]
$ go work init ./hello
go work init 命令告诉 go 为包含./hello 目录中的模块的工作空间创建一个 go.work 文件。go.work 文件的语法与 go.mod 相似
自动创建的 go.work 中的文件内容如下:
go 1.18
use ./hello
因此,在工作区的任何子目录中,该模块都将处于活动状态。
然后,运行工作区目录下的程序
在工作区目录中,运行:
# wade @ wade-virtual-machine in ~/workspace_test [23:02:48]
$ go run example.com/hello
us1uohzuy ,olleH
Go 命令包含工作区中的所有模块作为主模块。
这允许我们在模块中引用一个包,甚至在模块之外。在模块或工作区之外运行 go run 命令会导致错误,因为 go 命令不知道要使用哪些模块。
今天我们介绍了 Go 1.18 的一个新特性:Multi-Module 工作空间模型。它本质上仍然是解决本地发展需求的一种解决方案。
由于 go.mod 文件与项目密切相关,因此它们基本上是上传到 Git 存储库的,因此很难对其进行任何操作。所以我们只是将 go.work 构建为纯本地化且易于使用。
使用新的 go.work,您可以处理完全的本地文件,而不会影响开发团队的其他成员。
更多关于多模块工作区的知识,可以查看官方的教程。
对此感到疯狂,真的缺少一些东西。 我有webpack 4.6.0,webpack-cli ^ 2.1.2,所以是最新的。 在文档(https://webpack.js.org/concepts/mod
object Host "os.google.com" { import "windows" address = "linux.google.com" groups = ["linux"] } obj
每当我安装我的应用程序时,我都可以将数据库从 Assets 文件夹复制到 /data/data/packagename/databases/ .到此为止,应用程序工作得很好。 但 10 或 15 秒后
我在 cc 模式缓冲区中使用 hideshow.el 来折叠我不查看的文件部分。 如果能够在 XML 文档中做到这一点就好了。我使用 emacs 22.2.1 和内置的 sgml-mode 进行 xm
已结束。此问题不符合 Stack Overflow guidelines .它目前不接受答案。 我们不允许提出有关书籍、工具、软件库等方面的建议的问题。您可以编辑问题,以便用事实和引用来回答它。 关闭
根据java: public Scanner useDelimiter(String pattern) Sets this scanner's delimiting pattern to a patt
我读过一些关于 PRG 模式以及它如何防止用户重新提交表单的文章。比如this post有一张不错的图: 我能理解为什么在收到 2xx 后用户刷新页面时不会发生表单提交。但我仍然想知道: (1) 如果
看看下面的图片,您可能会清楚地看到这一点。 那么如何在带有其他一些 View 的简单屏幕中实现没有任何弹出/对话框/模式的微调器日期选择器? 我在整个网络上进行了谷歌搜索,但没有找到与之相关的任何合适
我不知道该怎么做,我一直遇到问题。 以下是代码: rows = int(input()) for i in range(1,rows): for j in range(1,i+1):
我想为重写创建一个正则表达式。 将所有请求重写为 index.php(不需要匹配),它不是以/api 开头,或者不是以('.html',或'.js'或'.css'或'.png'结束) 我的例子还是这样
MVC模式代表 Model-View-Controller(模型-视图-控制器) 模式 MVC模式用于应用程序的分层开发 Model(模型) - 模型代表一个存取数据的对象或 JAVA PO
我想为组织模式创建一个 RDF 模式世界。您可能知道,组织模式文档基于层次结构大纲,其中标题是主要的分组实体。 * March auxiliary :PROPERTIES: :HLEVEL: 1 :E
我正在编写一个可以从文件中读取 JSON 数据的软件。该文件包含“person”——一个值为对象数组的对象。我打算使用 JSON 模式验证库来验证内容,而不是自己编写代码。符合代表以下数据的 JSON
假设我有 4 张 table 人 公司 团体 和 账单 现在bills/persons和bills/companys和bills/groups之间是多对多的关系。 我看到了 4 种可能的 sql 模式
假设您有这样的文档: doc1: id:1 text: ... references: Journal1, 2013, pag 123 references: Journal2, 2014,
我有这个架构。它检查评论,目前工作正常。 var schema = { id: '', type: 'object', additionalProperties: false, pro
这可能很简单,但有人可以解释为什么以下模式匹配不明智吗?它说其他规则,例如1, 0, _ 永远不会匹配。 let matchTest(n : int) = let ran = new Rand
我有以下选择序列作为 XML 模式的一部分。理想情况下,我想要一个序列: 来自 my:namespace 的元素必须严格解析。 来自任何其他命名空间的元素,不包括 ##targetNamespace和
我希望编写一个 json 模式来涵盖这个(简化的)示例 { "errorMessage": "", "nbRunningQueries": 0, "isError": Fals
首先,我是 f# 的新手,所以也许答案很明显,但我没有看到。所以我有一些带有 id 和值的元组。我知道我正在寻找的 id,我想从我传入的三个元组中选择正确的元组。我打算用两个 match 语句来做到这
我是一名优秀的程序员,十分优秀!