系列索引
为什么以及什么
项目,依赖项和Gopls
最小版本选择
镜像,校验和和Athens
Gopls改进
vendor用法
序幕
这是一篇由Go团队成员Rohan Challa撰写的客座文章。他目前主要负责Gopl的相关工作
本篇是Bill Kennedy的一篇关于项目,依赖和gopls的文章的后续。他的文章表明,gopls不适用于模块,尤其是在编辑器内部的项目中添加和删除依赖项时。在过去的3个月中,我在Go团队中的工作主要是改进gopls对模块的支持。
介绍
当go命令需要下载新的依赖项来满足导入需要时,可以在运行命令的过程中更新项目的go.mod文件。由于许多编辑器在后台运行go命令,因此这些更改会在开发人员不知情的情况下发生。我们认为这给人一种令人困惑和不直观的编辑体验。
要解决此问题,Go 1.14支持一个新标志:-modfile。该标志指示go命令读取和写入替代go.mod的文件,而不是与项目关联的文件。gopls已更新为使用此新标记,以便编辑器可以提供建议,而不是在开发人员不知情的情况下直接更改项目的go.mod文件。这样,gopls为开发人员提供了为项目做出最佳决策所需的信息。
在本文中,我将向你展示gopls0.4.0版中的新功能,这些功能将改善编辑器对模块支持的体验。
演练
该帖子将作为Bill帖子的补充,并使用相同的示例代码。我们将使用类似的工作流程,演示gopls团队如何改善编辑器中添加和删除依赖的操作体验。这些功能适用于支持Language Server Protocol的任何编辑器。这里,我将使用带有Go扩展名 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项目的更多信息,请参阅文档。
代码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中的方法,就像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
image
保存文件后,图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的帖子中,旧版本的goplsSurface出现了一个诊断,其中包含有关导入的消息,该消息undeclared name: conf。现在,最新版本的gopls不会提供这种模糊的错误消息,而是提供帮助。
图2
[图片上传失败...(image-8b5d06-1589031784181)]
你可以在导入下方看到一条弯曲的线,表示存在警告。当你将鼠标悬停在上面,你会看到的警告,如图2所示。此消息表明conf模块没有列入该项目的go.mod文件,并且你需要将新的依赖添加到该go.mod文件,以满足导入。幸运的是,警告带有Quick Fix链接。
图3
image.png
如果仔细观察图3,你将看到Quick Fix链接。单击此链接将弹出一个选项,将模块添加到go.mod文件中。当选择添加选项时,go.mod文件将被更新,但未保存,因此你可以决定是否保留更改。
图4
image
未保存的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
image
打开go.mod文件,它应该如图5所示。应该在第5行上看到一条与该conf模块相关的波浪线。
图6
image
将鼠标悬停在模块上时,将在图6中看到警告。还为你提供了一个Quick Fix链接,单击该链接将提供一个从go.mod文件中删除依赖项的选项。
图7
image
图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
image
在图8中,你会看到一条建议链接,用于将conf模块从1.2.0版本升级到1.2.1版本。在撰写本文时,版本1.2.1是最新的最佳版本。当你单击此建议链接时,gopls会将依赖项升级到指定的版本。你还可以在go.mod文件顶部看到建议链接。该建议链接将升级具有单独建议的文件中的所有模块。
图9
image
单击任何一个建议链接之后,go.mod文件都会列出该conf模块的最新版本,如图9中的图像。
结论
gopls团队要感谢Bill提供了这样一个详细的文章,解释使用的gopls与模块的痛点。帖子中概述的步骤帮助我们测试并更好地理解了用户与模块的交互。体验报告非常有帮助,我们非常重视你的反馈。
将开发环境升级到Go 1.14并升级gopls到最新版本(v0.4.0)(包括预发行版)后,即可使用本文中描述的功能。
要查看这些新功能的实际效果,请看一下此录屏视频,这里演示了本文概述的功能。
有关于gopls的问题可以在问题跟踪中提交。
可以在Slack的#gopls频道内询问任何问题,请使用Invite app进行访问。












网友评论