暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

[译]模块(Modules)05:Gopls改进

不务正业的豆腐酱 2022-08-30
663

系列索引

[译]模块(Modules)04:第四部分:镜像,校验和,Athens

 [译]模块(Modules)03:最小版本选择

 [译]模块(Modules)02:项目依赖和Gopls

 [译]模块(Modules)01:为什么和做什么

序幕

「这是一篇由Go团队成员Rohan Challa撰写的客座文章。他目前主要负责Gopl的相关工作」

本篇是Bill Kennedy的一篇关于项目,依赖和gopls的文章[1]的后续。他的文章表明,`gopls`[2]不适用于模块,尤其是在编辑器内部的项目中添加和删除依赖项时。在过去的3个月中,我在Go团队中的工作主要是改进gopls
对模块的支持。

介绍

go
命令需要下载新的依赖项来满足导入需要时,可以在运行命令的过程中更新项目的go.mod
文件。由于许多编辑器在后台运行go
命令,因此这些更改会在开发人员不知情的情况下发生。我们认为这给人一种令人困惑和不直观的编辑体验。

要解决此问题,Go 1.14支持一个新标志:-modfile
。该标志指示go
命令读取和写入替代go.mod
的文件,而不是与项目关联的文件。gopls
已更新为使用此新标记,以便编辑器可以提供建议,而不是在开发人员不知情的情况下直接更改项目的go.mod
文件。这样,gopls
为开发人员提供了为项目做出最佳决策所需的信息。

在本文中,我将向你展示gopls
0.4.0版中的新功能,这些功能将改善编辑器对模块支持的体验。

演练

该帖子将作为Bill帖子的补充,并使用相同的示例代码。我们将使用类似的工作流程,演示gopls
团队如何改善编辑器中添加和删除依赖的操作体验。这些功能适用于支持Language Server Protocol[3]的任何编辑器。这里,我将使用带有Go扩展名[4] VS Code 编辑器。

首先,确认你的环境配置正确。

「代码1」

// Check Go plugin version : >= v0.13.0
$ code --list-extensions --show-versions

// Check gopls version : >= v0.4.0
$ gopls version

// Check Go Version : >= v1.14
$ go version


代码1显示了用于验证VS Code Go扩展的版本,gopls
以及正在使用的Go 的版本的命令。请务必确保VS Code 至少使用Go扩展程序的0.13.0版本,gopls
的0.4.0 版本和go
的1.14版本。

撰写本文时,版本0.4.0是gopls
的最新版本。

「代码2」

// To install the latest version of gopls.
$ cd $HOME
$ GO111MODULE=on go get golang.org/x/tools/gopls@latest


代码2显示了如何安装的最新版本gopls
。在你的$HOME
目录运行此命令。

模块缓存

正如Bill所做的那样,我将在开始之前清除模块缓存,保证使用的是一个干净的工作环境。这样我可以向你展示如何处理模块没有下载到本地模块缓存中的情况。

「代码3」

$ go clean -modcache


代码3显示了go clean
命令并使用-modcache
。在正常的工作流程中,这并不是必须执行的步骤。

新建项目

首先,我将创建一个新项目。有关使用模块创建新的Go项目的更多信息,请参阅文档[5]

「代码4」https://play.golang.org/p/4zDoHbGT4Mz

$ cd $HOME
$ mkdir modtest
$ cd modtest
$ touch main.go
$ go mod init modtest


代码4中的命令创建了一个新的项目文件夹,其中包含源代码文件:main.go
以及go.mod
用于创建模块的文件。

「代码5」

$ code .


运行代码5中的命令将启动VS Code并打开项目。这还将在后台自动启动gopls
服务。

应用代码

「代码6」https://play.golang.org/p/fUha75miwFB

01 package main
02
03 import (
04 "log"
05 )
06
07 func main() {
08 log.Println("This is package main")
09 }


首先,将代码6中的代码复制到main.go
文件中。

我希望该项目使用github.com/ardanlabs/conf[6]中的方法,就像Bill在他的帖子中所做的那样。

「代码7」https://play.golang.org/p/QioJFbiXGye

07 func main() {
08 var cfg struct {
09 Web struct {
10 APIHost string `conf:"default:0.0.0.0:3000"`
11 DebugHost string `conf:"default:0.0.0.0:4000"`
12 ReadTimeout time.Duration `conf:"default:5s"`
13 WriteTimeout time.Duration `conf:"default:5s"`
14 ShutdownTimeout time.Duration `conf:"default:5s"`
15 }
16 }
17
18 if err := conf.Parse(os.Args[1:], "SALES", &cfg); err != nil {
19 log.Fatal("parsing config : %w", err)
20 }
21 log.Println("This is package main")
22 }


将代码7中的代码添加到main
函数中并保存。

「图1」

保存文件后,图1显示了有关conf.Parse
使用的错误。由于模块缓存中没有关于conf
包的信息(记住,我在开始之前就清除了模块缓存)gopls
无法指导VS Code为conf
程序包添加导入。gopls
也找不到有关该包的任何信息。

添加依赖

因为gopls
仅了解标准库或本地模块缓存中的软件包,所以你需要手动添加导入。一旦程序包存在于本地缓存中,gopls
便可以在所有项目中为其自动添加导入。

「代码8」

03 import (
04 "log"
05 "os"
06 "time"
07
08 "github.com/ardanlabs/conf"
09 )


如代码8的第08行所示,在main.go
文件的import部分中为包添加一个conf
的import,然后保存。添加此导入后gopls
将会直接将模块下载到本地模块缓存中。一旦完成,conf.Parse
就可以解决对第22行的引用。请注意,你需要等待下载完成后,编辑器才可以解析参考并提供有关该模块的信息。

此时,在Bill的帖子中,旧版本的gopls
Surface出现了一个诊断,其中包含有关导入的消息,该消息「undeclared name: conf」。现在,最新版本的gopls
不会提供这种模糊的错误消息,而是提供帮助。

「图2」

你可以在导入下方看到一条弯曲的线,表示存在警告。当你将鼠标悬停在上面,你会看到的警告,如图2所示。此消息表明conf
模块没有列入该项目的go.mod
文件,并且你需要将新的依赖添加到该go.mod
文件,以满足导入。幸运的是,警告带有Quick Fix
链接。

「图3」

如果仔细观察图3,你将看到Quick Fix
链接。单击此链接将弹出一个选项,将模块添加到go.mod
文件中。当选择添加选项时,go.mod
文件将被更新,但未保存,因此你可以决定是否保留更改。

「图4」

未保存的go.mod
文件应类似于列出图4中的图像。由于gopls
下载了模块的最新版本,因此版本可能会有所不同。保存文件以保留更改。此时,具有所选版本的模块将记录在go.mod
中,并且在导入中带有警告消息的弯线消失了。

删除依赖项

现在,如果你改变主意,不想再使用该conf
软件包,该怎么办?

「代码9」https://play.golang.org/p/RwC0aWzXf3F

11 func main() {
12 log.Println("This is package main")
13 }


更改代码9中提供的main
函数中的代码,这将删除对conf
包的依赖。按下保存后,gopls
将组织导入并删除所有未使用的依赖项。

「代码10」https://play.golang.org/p/fUha75miwFB

01 package main
02
03 import (
04 "log"
05 )
06
07 func main() {
08 log.Println("This is package main")
09 }


代码10显示了保存main.go
文件后,清理导入后的文件效果。由于代码不再使用conf
依赖项,因此应将其从项目go.mod
文件中删除。

在Bill的上一篇文章中,他需要离开VS Code并运行go mod tidy
以清理项目go.mod
文件。现在,你可以从VS Code中 tidy go.mod
文件。

「图5」

打开go.mod
文件,它应该如图5所示。应该在第5行上看到一条与该conf
模块相关的波浪线。

「图6」

将鼠标悬停在模块上时,将在图6中看到警告。还为你提供了一个Quick Fix
链接,单击该链接将提供一个从go.mod
文件中删除依赖项的选项。

「图7」

图7显示了单击Quick Fix
选项后如何删除模块。完成此操作后,请不要忘记保存go.mod
文件。

升级依赖关系

另一个新功能是能够从VS Code中将依赖项升级到最新版本。此功能适用于任何支持模块的版本的Go。为了说明这一点,我需要将conf
模块的代码放回main
函数中。

「代码11」https://play.golang.org/p/NB6CMA52Zyf

01 package main
02
03 import (
04 "log"
05 "os"
06 "time"
07
08 "github.com/ardanlabs/conf"
09 )
10
11 func main() {
12 var cfg struct {
13 Web struct {
14 APIHost string `conf:"default:0.0.0.0:3000"`
15 DebugHost string `conf:"default:0.0.0.0:4000"`
16 ReadTimeout time.Duration `conf:"default:5s"`
17 WriteTimeout time.Duration `conf:"default:5s"`
18 ShutdownTimeout time.Duration `conf:"default:5s"`
19 }
20 }
21
22 if err := conf.Parse(os.Args[1:], "SALES", &cfg); err != nil {
23 log.Fatal("parsing config : %w", err)
24 }
25 log.Println("This is package main")
26 }


从代码11我们可以看见, main.go
再次使用conf
模块。接下来,我将故意在go.mod
文件中使用conf
模块的旧版本。

「代码12」

01 module modtest
02
03 go 1.14
04
05 require github.com/ardanlabs/conf v1.2.0


代码12显示了在我手动将模块从使用最新版本更改为版本1.2.0之后的go.mod
文件。保存更改后,会得到有关升级版本的建议。

「图8」

在图8中,你会看到一条建议链接,用于将conf
模块从1.2.0版本升级到1.2.1版本。在撰写本文时,版本1.2.1是最新的最佳版本。当你单击此建议链接时,gopls
会将依赖项升级到指定的版本。你还可以在go.mod
文件顶部看到建议链接。该建议链接将升级具有单独建议的文件中的所有模块。

「图9」

单击任何一个建议链接之后,go.mod
文件都会列出该conf
模块的最新版本,如图9中的图像。

结论

gopls
团队要感谢Bill提供了这样一个详细的文章,解释使用的gopls
与模块的痛点。帖子中概述的步骤帮助我们测试并更好地理解了用户与模块的交互。体验报告非常有帮助,我们非常重视你的反馈。

将开发环境升级到Go 1.14并升级gopls
到最新版本(v0.4.0)(包括预发行版)后,即可使用本文中描述的功能。

要查看这些新功能的实际效果,请看一下此录屏视频[7],这里演示了本文概述的功能。

有关于gopls
的问题可以在问题跟踪[8]中提交。

可以在Slack[9]的#gopls频道内询问任何问题,请使用Invite app[10]进行访问。

Reference

[1]

文章: https://www.ardanlabs.com/blog/2019/12/modules-02-projects-dependencies-gopls.html

[2]

gopls
: https://github.com/golang/tools/blob/master/gopls/doc/user.md

[3]

Language Server Protocol: https://microsoft.github.io/language-server-protocol/

[4]

Go扩展名: https://github.com/microsoft/vscode-go

[5]

文档: https://blog.golang.org/using-go-modules

[6]

github.com/ardanlabs/conf: https://pkg.go.dev/github.com/ardanlabs/conf

[7]

录屏视频: https://drive.google.com/file/d/1xcfz-Q465_j3WzLKY9i4nEq5WfP65EFu

[8]

问题跟踪: https://github.com/golang/go/issues/new/?title=x/tools/gopls:&body=%3C%21--%0APlease%20answer%20these%20questions%20before%20submitting%20your%20issue.%20Thanks%21%0AFor%20questions%20please%20use%20one%20of%20our%20forums%3A%20https%3A%2F%2Fgithub.com%2Fgolang%2Fgo%2Fwiki%2FQuestions%0A--%3E%0A%0A%23%23%23%20What%20version%20of%20Go%20are%20you%20using%20%28%60go%20version%60%29%3F%0A%0A%3Cpre%3E%0A%24%20go%20version%0A%0A%3C%2Fpre%3E%0A%0A%23%23%23%20Does%20this%20issue%20reproduce%20with%20the%20latest%20release%3F%0A%0A%0A%0A%23%23%23%20What%20operating%20system%20and%20processor%20architecture%20are%20you%20using%20%28%60go%20env%60%29%3F%0A%0A%3Cdetails%3E%3Csummary%3E%3Ccode%3Ego%20env%3C%2Fcode%3E%20Output%3C%2Fsummary%3E%3Cbr%3E%3Cpre%3E%0A%24%20go%20env%0A%0A%3C%2Fpre%3E%3C%2Fdetails%3E%0A%0A%23%23%23%20What%20did%20you%20do%3F%0A%0A%3C%21--%0AIf%20possible%2C%20provide%20a%20recipe%20for%20reproducing%20the%20error.%0AA%20complete%20runnable%20program%20is%20good.%0AA%20link%20on%20play.golang.org%20is%20best.%0A--%3E%0A%0A%0A%0A%23%23%23%20What%20did%20you%20expect%20to%20see%3F%0A%0A%0A%0A%23%23%23%20What%20did%20you%20see%20instead%3F%0A

[9]

Slack: https://gophers.slack.com/

[10]

Invite app: https://invite.slack.golangbridge.org/




文章转载自不务正业的豆腐酱,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论