惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
罗磊的独立博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
Martin Fowler
Martin Fowler
G
GRAHAM CLULEY
Simon Willison's Weblog
Simon Willison's Weblog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
V
Vulnerabilities – Threatpost
云风的 BLOG
云风的 BLOG
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
量子位
Stack Overflow Blog
Stack Overflow Blog
Recent Announcements
Recent Announcements
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
I
Intezer
Scott Helme
Scott Helme
A
About on SuperTechFans
博客园 - 司徒正美
Hacker News: Ask HN
Hacker News: Ask HN
The GitHub Blog
The GitHub Blog
Forbes - Security
Forbes - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Spread Privacy
Spread Privacy
T
Tailwind CSS Blog
S
Security Affairs
宝玉的分享
宝玉的分享

文章列表 on polarisxu

这道题正确率竟然只有 22% Go 开源项目推荐:一个简单的 Go 练手项目 go test 如何禁用缓存? Go1.18 快讯:constraints 包被移除标准库 跟着 Go 作者学泛型 「2022 版」轻松搞定 Go 开发环境 鹅厂小哥用行动反对加班:程序员加班能被终结吗? Go 为什么选择 Gopher 作为吉祥物? 本地如何配置多个 GitHub/Gitee 账号? 为 Java 开发者准备的 Go 教程 02:Java 有而 Go 无 GitHub 发现了 studygolang 项目依赖的漏洞 Typora 宣布收费后,这款开源 Markdown 编辑器火了 为 Java 开发者准备的 Go 教程 01:漫游了 我的 2021 年终总结 泛型版 singleflight:Go 中如何防止缓存击穿? 2021 年你写了多少代码?这个 Go 工具帮你统计 Go1.18 新特性:TryLock Go 泛型入门教程 程序员瑞士军刀:各种结构的转换工具 终于有 Go 版的 Elasticsearch 了 Go泛型系列:maps 包讲解 Go 1.18 中的 any 是什么? Go1.18 快讯:新的 IP 包 Go编程模式:详解函数式选项模式 Go泛型系列:slices 包讲解 Nginx 竟然也有 playground — Go 语言构建的 Go泛型系列:Go1.18 类型约束那些事 Go1.18 快讯:Module 工作区模式 Go1.18 快讯:新增的 Cut 函数太方便了 Go1.18 快讯:废弃了这个 API Go1.18 快讯:新增字符串 Clone API Go:如何获得项目根目录? Go 如何获取和设置环境变量 重磅变动:更快找到微信公众号里的Go文章 Go 这样设置版本号:我们的项目也可以 假期结束,推荐 2 本 manning 出的 Go 图书 Go Fiber 框架系列教程 04:测试应用 Go Fiber 框架系列教程 03:中间件 Go泛型系列:提前掌握Go泛型的基本使用 推荐一个 Go GUI 实战项目 Go Fiber 框架系列教程 02:详解相关 API 的使用 Go Fiber 框架系列教程 01: 和 Express 对比学习 Go Module:私有不合规库怎么解决引用问题 Go1.17 新特性:go get 变了 Go1.17 新特性:testing 包的相关变化 StackOverflow 上关于 Go select 死锁的问题 新书推荐:用 Gin 框架构建分布式应用 Go 官网要变天。。。 Gin 这是要成为 Go 官方框架? 扬眉吐气:刚刚,Go 已经默认支持泛型了 Go 1.17 新特性:Module 有哪些变化? Go 第三方库推荐:类型转换如此简单 担心密码提交到 GitHub?建议使用这个 Go 开源工具 Go 的时间格式化为什么是 2006-01-02 15:04:05? GitHub 为 Go 社区带来安全支持 Go开源项目推荐:500行代码确认请求时间花在哪 一道关于 len 函数的诡异 Go 面试题解析 厉害了我的 Go:推荐系统都有开源实现 Go1.17 新特性:新版构建约束 这个工具真好:看看你的Go项目依赖有无漏洞 网友很强大,发现了Go并发下载的Bug Rust 劝退系列 09:函数 Go项目实战:一步步构建一个并发文件下载器 这本 Go 新书挺期待的:100 个常见错误 Go 启用新的官方问答社区 这是要干嘛?!微软招 Go 编译器全职开发人员 Go1.17 快报之标准库越来越注重易用性 Go1.17 新特性之切片变数组 回顾 Go 官网的演变史 站长8年前的Go代码竟然进入大厂的项目里了 Go图书翻译:一个好消息,一个坏消息 不怕烂尾!决定组织翻译这本 Go 图书 Rust 劝退系列 08:模式匹配 一本花了2.5年写成的Go免费在线图书 被黑惨了:一句话,说明自己会 Go,咋整? Go1.16 中的新函数 signal.NotifyContext 怎么用? Go 1.17 新特性提前学之测试执行随机化 Rust 劝退系列 07:流程控制 官方的 Go 多版本管理:使用和原理 Rust新书:给你一个劝退的理由 周刊题解:常量表达式这个规则应该了解下 盘点那些使用 Go 语言的国外公司 编写了50万行Go代码是一种什么体验 Rust 劝退系列 06:常量 Uber 使用 Go 的规模这么大?!都自己定制的 Go 编译器了 Go Team Leader — rsc 大神新开源了一个库,增强模板功能 再一次看到了 Go 的节制:int128 类型要不要支持? Rust 劝退系列 05:复合数据类型 「卷」有理论依据:海勒姆定律—Go又是怎么卷的 Go 真的也可以进行 GUI 开发:还有这样的图书呢 Rust 劝退系列 04:基本数据类型 我的 Go 语言书单 Rust 劝退系列 03:变量 我又来推荐免费 Go 新书了:一本用 Go 讲架构的书 注释竟然还有特殊用途?一文解惑 //go:linkname 指令 这个功能,公众号、微信群会不会被玩坏? 一道 Go 闭包题,面试官说原来自己答错了:面别人也涨知识 Rust 劝退系列 02:第一个 Rust 程序 Rust 劝退系列 01:打造开发环境 答应我,这次一定彻底搞懂 Go 中的类型别名
通过一个例子让你彻底掌握 Go 工作区模式
2022-10-23 · via 文章列表 on polarisxu

大家好,我是 polarisxu。

早在 Go1.18 快要发布时,我就试用了工作区(workspace)模式,并写了一篇介绍文章:Go1.18 快讯:Module 工作区模式

然而,Go1.18 正式发布后,工作区模式有点变化,导致那篇文章的部分内容不试用了,于是今天重新补一篇,因为工作区模式真的很有用。

工作区模式(Workspace mode),可不是之前 GOPATH 时代的 Workspace,而是希望在本地开发时支持多 Module。

01 缘起

为了大家全面理解工作区模式,通过一个具体例子讲解。

本地有两个项目,分别是两个 module:mypkg 和 example。(Windows 系统请按自己方式创建目录)

$ cd ~/
$ mkdir polarisxu
$ cd polarisxu
$ mkdir mypkg example
$ cd mypkg
$ go mod init github.com/polaris1119/mypkg
$ touch bar.go

在 bar.go 中增加如下示例代码:

package mypkg

func Bar() {
    println("This is package mypkg")
}

接着,在 example 模块中处理:

$ cd ~/polarisxu/example
$ go mod init github.com/polaris1119/example
$ touch main.go

在 main.go 中增加如下内容:

package main

import (
    "github.com/polaris1119/mypkg"
)

func main() {
    mypkg.Bar()
}

这时候,如果我们运行 go mod tidy,肯定会报错,因为我们的 mypkg 包根本没有提交到 github 上,肯定找不到。

$ go mod tidy
....
fatal: repository 'https://github.com/polaris1119/mypkg/' not found

go run main.go 也就不成功。

我们当然可以提交 mypkg 到 github,但我们每修改一次 mypkg,就需要提交(而且每次提交之后需要在 example 中 go get 最新版本),否则 example 中就没法使用上最新的。

针对这种情况,目前是建议通过 replace 来解决,即在 example 中的 go.mod 增加如下 replace:(v1.0.0 根据具体情况修改,还未提交,可以使用 v1.0.0)

module github.com/polaris1119/example

go 1.19

require github.com/polaris1119/mypkg v1.0.0

replace github.com/polaris1119/mypkg => ../mypkg

再次运行 go run main.go,输出如下:

$ go run main.go
This is package mypkg

当都开发完成时,我们需要手动删除 replace,并执行 go mod tidy 后提交,否则别人使用就报错了。

这还是挺不方便的,如果本地有多个 module,每一个都得这么处理。

02 工作区模式

针对上面的这个问题,Michael Matloob 提出了 Workspace Mode(工作区模式)。相关 issue 讨论:cmd/go: add a workspace mode这里是 Proposal 。并在 Go1.18 中发布了。

因此,要使用工作区,请确保 Go 版本在 1.18+。

我本地当前版本:

$ go version
go version go1.19.2 darwin/arm64

通过 go help work 可以看到 work 相关命令:

$ 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 相关命令,Go 其他命令也会涉及工作区内容,比如 go run、go build 等。

根据这个提示,我们初始化 workspace:

$ cd ~/polarisxu
$ go work init mypkg example
$ tree
.
├── example
│   ├── go.mod
│   └── main.go
├── go.work
└── mypkg
    ├── bar.go
    └── go.mod

注意几点:

  • 多个子模块应该在一个目录下(或其子目录)。比如这里的 polarisxu 目录;(这不是必须的,但更好管理,否则 go work init 需要提供正确的子模块路径)
  • go work init 需要在 polarisxu 目录执行;
  • go work init 之后跟上需要本地开发的子模块目录名;

打开 go.work 看看长什么样:

go 1.19

use (
    ./example
    ./mypkg
)

go.work 文件的语法和 go.mod 类似(go.work 优先级高于 go.mod),因此也支持 replace。

注意:实际项目中,多个模块之间可能还依赖其他模块,建议在 go.work 所在目录执行 go work sync

现在,我们将 example/go.mod 中的 replace 语句删除,再次执行 go run main.go(在 example 目录下),得到了正常的输出。也可以在 polarisxu 目录下,这么运行:go run example/main.go,也能正常。

注意,go.work 不需要提交到 Git 中,因为它只是你本地开发使用的。

当你开发完成,应该先提交 mypkg 包到 GitHub,然后在 example 下面执行 go get:

$ go get -u github.com/polaris1119/mypkg@latest

然后禁用 workspace(通过 GOWORK=off 禁用),再次运行 example 模块,是否正确:

$ cd ~/polarisxu/example
$ GOWORK=off go run main.go

目前 VSCode 的 go 插件已经支持 workspace,不需要做什么配置就可以愉快的玩耍。

03 总结

在 GOPATH 年代,多 GOPATH 是一个头疼的问题。当时没有很好的解决,Module 就出现了,多 GOPATH 问题因此消失。但多 Module 问题随之出现。Workspace 方案较好的解决了这个问题。