Gopls v0.17.0 版本发布

go install golang.org/x/tools/gopls@v0.17.0-pre.4

新的支持策略

在此版本中,我们将官方支持窗口缩窄,以与Go 支持策略保持一致。这将大大降低我们针对旧版本 Go 进行测试的成本,使我们能够花费更多时间来修复错误并添加对运行近期版本 Go 的大多数 gopls 用户有益的功能。

此次缩窄在两个维度上进行:构建兼容性是指可用于构建 gopls 的 Go 工具链版本,而go 命令兼容性是指 gopls 可用于列出工作区中包和模块信息的 go 命令版本。

构建兼容性:最新的主 Go 版本

正如v0.16.0 版本说明中所述,构建最新版本的 gopls 现在需要最新的主 Go 工具链版本。因此,此版本(gopls@v0.17.0)必须使用 Go 1.23.0 或更高版本进行构建。得益于自动工具链升级,如果您的系统 Go 版本至少为 Go 1.21.0 并且设置了 GOTOOLCHAIN=auto(默认设置),go 命令将自动按需下载新的 Go 工具链,类似于升级模块依赖。

Go 命令兼容性:最近的 2 个主 Go 版本

gopls@v0.17.x 版本将是 gopls 最后一个名义上支持集成超过最近 2 个 Go 版本以内的版本。过去,我们暗示支持最多 4 个版本,但实际上我们没有资源来修复仅存在于旧 Go 版本中的错误。在 gopls@v0.17.0 中,我们将此尽力支持的范围缩窄到 3 个版本,这主要是因为用户至少需要 Go 1.21 才能从自动工具链升级中受益(见上文)。

从 gopls@v0.18.0 开始,我们将仅正式支持与最近 2 个主 Go 命令版本集成。这与 Go 支持策略一致。有关详细信息,请参阅 golang/go#69321(或此评论)。

我们不会阻止 gopls 与旧版 Go 版本一起使用(就像我们不禁止与任意go/packages驱动程序集成一样),但我们不会针对旧版 Go 版本运行集成测试,也不会修复仅在与旧版 Go 版本一起使用时才存在的错误。

配置更改

  • fieldalignment 分析器(以前默认禁用)已被移除:它与 v0.16.0 显示的悬停大小/偏移量信息重复,并且其诊断信息令人困惑。
  • undeclaredname 分析器已被替换为常规代码操作。
  • gopls 所有代码操作的类型(标识符)已更改为使用更具体的层级名称。例如,“Inline call”已从 refactor.inline 更改为 refactor.inline.call。这允许客户端更精确地请求特定的代码操作。用户手册现在包含每个代码操作文档中的标识符。
  • 实验性的 allowImplicitNetworkAccess 设置已根据 gopls@v0.16.0 中的弃用而被移除。有关详细信息,请参阅 golang/go#66861。

新功能

重构

此版本包含多项与重构相关的新功能。此外,它还修复了现有重构操作中许多错误,主要涉及提取内联

这些改进使我们朝着提供更强大、更完整的重构工具集的长期目标迈进。我们还有很多工作要做,这项工作将持续到 2025 年。

移动参数重构

Gopls 现在提供代码操作,可以将函数和方法参数在函数签名中向左或向右移动,并更新所有调用者。

不幸的是,没有原生的 LSP 操作可以为任意“更改签名”重构提供良好的用户界面。我们计划在 VS Code 中构建这样一个界面。短期内,我们通过调用 func 关键字的“重命名”操作,使得表达更复杂的参数转换成为可能。此用户界面是临时的权宜之计,直到有更好的机制可用于启用客户端对话框的 LSP 命令。

将声明提取到新文件

Gopls 现在提供另一项代码操作“Extract declarations to new file”(refactor.extract.toNewFile),该操作将选定的代码段移动到同一包中新创建的文件。创建的文件名选择为遇到的第一个 {function, type, const, var} 名称。此外,还会根据需要添加或删除导入声明。

用户可以通过选择函数名、关键字 funcconstvartype,或将光标放在它们上面而不选择,或选择整个声明或多个声明来调用此代码操作。

为了避免歧义和意外,某些类型的声明的部分选择无法调用此代码操作。

提取常量

当选中的是常量表达式时,gopls 现在提供“Extract constant”而不是“Extract variable”,并生成 const 声明而不是局部变量。

此外,提取常量或变量现在可以在顶层工作,不在任何函数内部。

根据函数调用生成缺失的方法

当您尝试调用一个类型上不存在该方法的类型时,编译器会报告错误,例如“type T has no field or method f”。Gopls 现在提供一项新的代码操作“Declare missing method of T.f”,其中 T 是具体类型,f 是未定义的函数。存根方法的签名会根据调用的上下文进行推断。

为函数或方法生成测试

如果选中的代码块是函数或方法声明 F 的一部分,gopls 将提供“Add test for F”代码操作,该操作会在相应的 _test.go 文件中为选中的函数添加一个新的测试。生成的测试会考虑其签名,包括输入参数和返回值。

由于此功能由服务器(gopls)实现,因此与所有支持 LSP 的编辑器兼容。VS Code 用户可以继续使用客户端命令 Go: Generate Unit Tests For file/function/package,该命令会运行gotests工具。

初步支持拉取诊断

当使用选项 "pullDiagnostics": true 初始化时,gopls 将声明支持 textDocument.diagnostic 客户端能力,允许编辑器使用 textDocument/diagnostic 请求直接从 gopls 请求诊断,而不是等待 textDocument/publishDiagnostics 通知。此功能默认关闭,直到拉取诊断的功能集与推送诊断的功能集相当。

悬停改进

textDocument/hover 响应已略微调整了 markdown 渲染,并包含以下附加信息:

  • 悬停在标准库符号上现在会显示该符号首次出现的 Go 版本信息。例如,悬停在 errors.As 上会显示“Added in go1.13”。
  • 悬停在包声明的包名称上会包含额外的包元数据。

类型顶级构造函数的语义令牌修饰符

语义令牌响应现在包含每个符号类型的顶级构造函数的附加修饰符:interfacestructsignaturepointerarraymapslicechanstringnumberboolinvalid。编辑器可以使用此信息进行语法着色。

identvalues 的 SignatureHelp。

现在,函数签名帮助可以在任何具有函数签名的标识符上使用,而不仅仅是在正在调用的函数的括号内。

跳转到汇编定义

对函数引用的 Definition 查询会跳转到函数的 Go func 声明。如果函数是用 C 或汇编实现的,则函数没有函数体。执行第二个 Definition 查询(当已经在 Go 声明处时)将导航到汇编实现。

yield 分析器

新的 yield 分析器可检测 Go 1.23 迭代器中使用 yield 函数的错误,例如未能检查其布尔结果并跳出循环。

waitgroup 分析器

新的 waitgroup 分析器可检测对 sync.WaitGroupAdd 方法的调用,这些调用(错误地)在新 goroutine 中进行,导致 AddWait 发生竞争。(此检查等同于staticcheck 的 SA2000,但默认启用。)


本文档的源代码可以在 golang.org/x/tools/gopls/doc 下找到。