Zed 中的 Go 语言支持:gopls 配置、Inlay Hints、Code Lens 与 Delve 调试实战
Zed 内置了完整的 Go 语言支持,将解析(Tree-sitter)、静态分析(gopls)与调试(Delve)三大能力开箱即用地集成进编辑器。本文基于官方文档(见 docs/src/languages/go.md),结合仓库源码(crates/languages/src/go.rs、crates/dap_adapters/src/go.rs 等)逐层拆解 Go 环境的初始化、内联提示与代码镜头开关、基于 Delve 的四种调试模式,以及 Tailwind CSS 语言服务器在 Templ 中的联动用法。读完你可以按自己的项目配置一套完整的"编辑—提示—测试—调试"Go 工作流。
Go 支持全景:解析器、语言服务器与调试适配器
文档开头明确了 Zed 对 Go 的三层技术底座:
- 语法解析(Tree-sitter):使用
tree-sitter-go为.go文件提供语法树与高亮; - 语言服务器(Language Server):使用 Go 官方工具链中的
gopls,负责补全、诊断、重构、语义高亮等; - 调试适配器(Debug Adapter):使用
delve(dlv)作为 Go 程序的 DAP 调试后端。
该结论在仓库源码中得到印证。语言注册表 crates/languages/src/lib.rs 中,go、gomod、gowork 三种语言均挂载了 go_lsp_adapter 与共享的 go_context_provider,而 go 语言还额外注册了语义 Token 规则(go::semantic_token_rules())。语法层面,crates/grammars/src/grammars.rs 把 go、gomod、gowork 分别映射到 tree-sitter-go、tree-sitter-go-mod、tree-sitter-gowork;对应的高亮与可运行项查询位于 crates/grammars/src/go/highlights.scm、crates/grammars/src/go/runnables.scm、crates/grammars/src/gomod/highlights.scm 与 crates/grammars/src/gowork/highlights.scm。
Setup:以官方 Go 模块工具安装 gopls
文档给出一个明确建议:用 Go 自身的包管理工具安装 gopls,而不要用 Homebrew 或 Linux 发行版的包管理器,因为 go install 能保证 gopls 与你的 Go 工具链版本匹配、始终可更新到最新版,避免发行版滞后导致的协议不兼容。
- 先彻底卸载系统包管理器安装的任何 gopls 版本:
# MacOS homebrew
brew remove gopls
# Ubuntu
sudo apt-get remove gopls
sudo snap remove gopls
# Arch
sudo pacman -R gopls
- 使用 Go 模块工具安装/更新到最新版:
go install golang.org/x/tools/gopls@latest
- 确认 gopls 位于 PATH 中:
which gopls
gopls version
如果 gopls 找不到,通常需要把 Go bin 目录加入 shell 配置,例如在 .zshrc / .bash_profile 中添加:
export PATH="$PATH:$HOME/go/bin"
源码层面:Zed 如何发现并兜底安装 gopls
从源码看,GoLspAdapter 实现了完整的"优先用户安装、失败自动安装"逻辑(见 crates/languages/src/go.rs):
- 发现用户安装的二进制:
check_if_user_installed通过which("gopls")定位 PATH 中的可执行文件,并附加统一启动参数-mode=stdio(见 crates/languages/src/go.rs),即走 LSP 标准的 stdio 通道; - 自动安装兜底:当 gopls 不在 PATH 中时,Zed 会先探测
go命令是否可用——若go都不存在,则会弹出通知并中止安装;否则执行go install golang.org/x/tools/gopls@latest(源码中显式设置GO111MODULE=on与GOBIN指向 Zed 的托管目录); - 版本化缓存:安装完成后,二进制会被重命名为形如
gopls_{gopls版本}_go_{go版本}的文件进行缓存与去重(gopls_{version}_go_{go_version}),再次启动时可直接复用已有缓存,避免反复重装。因此即使你手动安装失败,只要系统中有go,Zed 也能自行完成 gopls 的拉取与维护。
值得一提的是,Zed 启动 gopls 时还会注入一组默认初始化选项,默认配置中 usePlaceholders 为 false,并且内联提示、test 代码镜头与语义 Token 均按下面两节所述默认开启(见 crates/languages/src/go.rs)。
Inlay Hints(内联提示)默认值与覆盖方式
Zed 在启动 gopls 时会下发以下 hints 初始化选项,让语言服务器在编辑器设置中启用了内联提示时返回对应提示:
"hints": {
"assignVariableTypes": true,
"compositeLiteralFields": true,
"compositeLiteralTypes": true,
"constantValues": true,
"functionTypeParameters": true,
"parameterNames": true,
"rangeVariableTypes": true
}
各选项含义简述:
| 选项 | 作用 |
|---|---|
assignVariableTypes |
在 :=/= 赋值处内联显示推导出的变量类型 |
compositeLiteralFields |
在复合字面量中内联显示字段名 |
compositeLiteralTypes |
在复合字面量中内联显示类型名 |
constantValues |
内联显示常量值 |
functionTypeParameters |
内联显示函数调用的类型参数(泛型) |
parameterNames |
在调用处内联显示形参名(用于字面量参数) |
rangeVariableTypes |
在 range 循环变量处内联显示类型 |
若希望针对项目做定制,可在项目 .zed/settings.json 或全局用户设置中通过 lsp → gopls → initialization_options 覆盖默认值:
"lsp": {
"gopls": {
"initialization_options": {
"hints": {
// 只需列出要覆盖的项,未列出的保持 Zed 默认值
"parameterNames": false
}
}
}
}
覆盖并非"整体替换":源码中 Zed 先把上述默认配置构造为 JSON,再通过 merge_json_value_into 将用户在 initialization_options 中提供的覆盖项递归合并进默认配置(见 crates/languages/src/go.rs),因此你只需书写想要改动的键。文档中也说明,更多选项细节可查阅 gopls 官方文档的 inlayHints 章节。
Code Lens(代码镜头):默认开启 test,运行测试/基准测试
Zed 默认只为 gopls 开启 test 代码镜头(源码中默认配置为 "codelenses": { "test": true },见 crates/languages/src/go.rs)。开启后,*_test.go 文件中的 Test 与 Benchmark 函数上方会出现 "run test" 与 "run benchmark" 之类的可点击入口。
要看到这些入口,需要先在设置中启用代码镜头能力:
{
"code_lens": "on"
}
然后可在 settings.json 中按需覆盖默认的代码镜头集合(除 test 外,还可启用 generate、tidy、vendor 等针对 go.mod 的维护动作):
{
"lsp": {
"gopls": {
"initialization_options": {
"codelenses": {
"test": true,
"generate": true,
"regenerate_cgo": true,
"tidy": true,
"upgrade_dependency": true,
"vendor": true
}
}
}
}
}
关于各 codelenses 行为的完整说明可参考 gopls 官方文档中的 code lenses 章节。
代码镜头背后:点击后发生了什么
当你在代码镜头上点击运行时,gopls 会通过 LSP 的 workspace/executeCommand 发送 gopls.run_tests 命令。Zed 的 client_command 专门拦截该命令,并将其转换为一条 go test 任务调度(见 crates/languages/src/go.rs)。任务模板在 crates/languages/src/go.rs 中构造:
- 测试模式会附加
-test.fullpath=true、默认-timeout 30s,并通过-run的正则精确匹配函数名(单个测试用^TestXxx$,多个用^(A|B)$); - 基准测试模式会追加
-benchmem、-run=^$与对应的-bench正则; - 工作目录取自触发代码镜头所在文件的 URI 的父目录。
这也解释了为什么 Zed 中 gopls 的 test code lens 能"一键"跑起单个用例,而无须离开编辑器。
Debugging:基于 Delve 的零配置调试
Zed 对 Go 测试与入口点(func main)支持零配置调试。直接运行 {#action debugger::Start} 动作(快捷键见你的 keymap 中 debugger::Start 绑定),即可看到 Zed 根据当前上下文(光标所在文件/测试)预生成的一批调试任务。
需要更多控制时,可在项目根目录创建 .zed/debug.json 添加自定义调试配置,所有配置项由内置 Delve 适配器 GoDebugAdapter 提供 schema 校验(其字段定义见 crates/dap_adapters/src/go.rs)。下面按文档整理四种典型场景。
说明:Delve 官方文档中有 launch / attach 配置的完整说明,本文只覆盖 Zed 中最常用的形式。
场景一:调试 Go 包(debug 模式)
调试某个具体包时,把 Delve 的 mode 设为 "debug",此时 program 应填写包名或包所在目录:
[
{
"label": "Go (Delve)",
"adapter": "Delve",
"program": "$ZED_FILE",
"request": "launch",
"mode": "debug"
},
{
"label": "Run server",
"adapter": "Delve",
"request": "launch",
"mode": "debug",
// For Delve, the program can be a package name
"program": "./cmd/server"
// "args": [],
// "buildFlags": [],
}
]
$ZED_FILE 是 Zed 内置的上下文变量,指当前活动文件;program 也可以直接写形如 ./cmd/server 的包路径。需要为被调试程序传参时放开 args,需要定制编译标志(如构建标签)时放开 buildFlags。
场景二:调试 Go 测试(test 模式)
调试某个包的测试时,把 mode 设为 "test"。此时 program 依旧是包名,可用 buildFlags 设置构建标签等编译期选项,用 args 向测试二进制传参(详见 go help testflags):
[
{
"label": "Run integration tests",
"adapter": "Delve",
"request": "launch",
"mode": "test",
"program": ".",
"buildFlags": ["-tags", "integration"]
// To filter down to just the test your cursor is in:
// "args": ["-test.run", "$ZED_SYMBOL"]
}
]
$ZED_SYMBOL 同样由 Zed 注入,代表光标所在的测试/符号名;配合 -test.run 即可把调试范围收敛到光标所在的单个测试上。
场景三:编译与调试分离(exec 模式)
如果项目需要以特定命令先编译出可执行文件,再对其调试,则使用 Delve 的 "exec" 模式:此时 program 指向编译产物,build 字段定义编译命令。文档给出的示例先用 go test -c 把单元测试编译成二进制,再进行调试:
[
{
"label": "Debug Prebuilt Unit Tests",
"adapter": "Delve",
"request": "launch",
"mode": "exec",
"program": "${ZED_WORKTREE_ROOT}/__debug_unit",
"args": ["-test.v", "-test.run=${ZED_SYMBOL}"],
"build": {
"command": "go",
"args": [
"test",
"-c",
"-tags",
"unit",
"-gcflags\"all=-N -l\"",
"-o",
"__debug_unit",
"./pkg/..."
]
}
}
]
这里 -gcflags"all=-N -l" 用于关闭优化与内联,保证断点命中的是源码行;-o __debug_unit 指定产物文件名;调试完成后该配置可让 Delve 直接运行预编译好的测试二进制,适合需要精确复现编译参数或明显加快启动速度的场景。${ZED_WORKTREE_ROOT} 是 Zed 内置的工作区根目录变量。
场景四:连接已运行的 Delve 实例(远程调试)
当需要连接一台不在本机运行的 Delve 实例(例如远程开发机或容器中已启动的 dlv dap)时,用 tcp_connection 字段来指定 Zed 连接 Delve 的主机与端口:
[
{
"adapter": "Delve",
"label": "Connect to a running Delve instance",
"program": "/Users/zed/Projects/language_repositories/golang/hello/hello",
"cwd": "/Users/zed/Projects/language_repositories/golang/hello",
"args": [],
"env": {},
"request": "launch",
"mode": "exec",
"stopOnEntry": false,
"tcp_connection": { "host": "127.0.0.1", "port": 53412 }
}
]
该场景下 Zed 不会新启动一个 Delve 进程,而是直接复用已存在的实例。由此带来的结果是:Zed 中不会出现对应的调试终端——被调试程序的 stdin/stdout 由那个外部 Delve 实例直接处理,你需要在其运行的终端里与 Delve 交互(例如查看 fmt.Println 输出)。
Delve 适配器支持哪些配置字段
除了文档示例中出现的字段,crates/dap_adapters/src/go.rs 的 schema 还定义了如下常用选项,可用在 .zed/debug.json 的 launch 配置中:
| 字段 | 类型/取值 | 说明 |
|---|---|---|
cwd |
string | 被调试程序的工作目录,默认 ${ZED_WORKTREE_ROOT} |
args |
array / string | 传给程序的命令行参数 |
env / envFile |
object / string | 程序环境变量,或从 .env 文件加载(Zed 会代读 envFile 并合并进 env,见 crates/dap_adapters/src/go.rs) |
buildFlags |
array | 传给 Go 编译器的标志 |
mode |
debug / test / exec / replay / core | 调试模式 |
stopOnEntry |
boolean | 启动或附加后是否自动停在程序入口,默认 false |
showLog |
boolean | 是否显示 delve 的 --log 日志 |
dlvFlags |
array | 透传给 dlv 的额外标志 |
backend |
default / native / lldb / rr | delve 使用的调试后端 |
trace |
verbose / trace / log / info / warn / error | DAP 日志级别,默认 error |
stackTraceDepth |
number | 堆栈最大深度,默认 50 |
substitutePath |
array(from/to) |
本地与远程路径映射,用于远程调试源码跳转 |
console |
internalConsole / integratedTerminal | 调试器启动位置 |
另外,Zed 的 Delve 支持"自动安装":如果系统 PATH 中没有 dlv,Zed 会先确认 go 可用,然后执行 go install github.com/go-delve/delve/cmd/dlv@latest 将其装入托管目录(见 crates/dap_adapters/src/go.rs);实际通信时通过一个 delve-shim-dap 桥接程序把 DAP 转发给 dlv dap(默认监听本机随机端口),只有在指定 tcp_connection 时才直连外部实例而不启用该桥接(见 crates/dap_adapters/src/go.rs)。
Go Mod / Go Sum / Go Work:模块文件的语法支持
除 .go 源文件外,Zed 对 Go 模块元数据文件也提供基础的语法高亮支持,这些文件均没有独立语言服务器(Language Server: N/A),语言能力由 Tree-sitter 提供:
- Go Mod:语法来自
camdencheek/tree-sitter-go-mod; - Go Sum:语法来自
amaanq/tree-sitter-go-sum; - Go Work:语法来自
tree-sitter-go-work。
就当前仓库内置注册表而言,gomod 与 gowork 均作为内置语言注册并复用 gopls 适配器与 Go 上下文(见 crates/languages/src/lib.rs),语法映射见 crates/grammars/src/grammars.rs 与 crates/grammars/src/gomod/config.toml、crates/grammars/src/gowork/config.toml。你可以据此推断:对 .go.mod / .go.work 这类文件,Zed 的编辑体验以高亮、括号匹配与基于 Tree-sitter 的结构能力为主,符号跳转、诊断等智能能力仍需要依赖打开其所属 Go 模块后 gopls 提供的服务。
在 Templ 文件中启用 Tailwind CSS 语言服务器
Templ 是 Go 生态中一个 HTML 模板语言。如果你希望 .templ 文件里也能获得 Tailwind CSS 的补全与检查能力(例如在 class="..." 中提示颜色、间距等工具类),需要做两件事:把 tailwindcss-language-server 加入 Templ 语言的服务器列表,并告诉 Tailwind 把 .templ 当作 HTML 解析。在 settings.json 中写入:
{
"languages": {
"Templ": {
"language_servers": ["tailwindcss-language-server", "..."]
}
},
"lsp": {
"tailwindcss-language-server": {
"settings": {
"includeLanguages": {
"templ": "html"
},
"experimental": {
"classRegex": ["class=\"([^\"]*)\""]
}
}
}
}
}
Note: 与其他语言不同,你必须显式告诉 Tailwind 把
.templ文件当作 HTML 处理。
配置完成后,.templ 文件中 class="..." 属性内即可获得 Tailwind CSS 的类名补全。这背后的机制与 Zed 内置的 Tailwind 适配器注册方式一致:tailwindcss-language-server 被注册为全局可用的语言服务器,可通过 languages 下的 language_servers 设置为任意语言开启(参见 crates/languages/src/lib.rs 中 register_available_lsp_adapter 的注册逻辑与注释说明);includeLanguages 让 Tailwind 用 HTML 规则解析 templ,而 classRegex 则指定在哪些属性中识别 class 名。
小结
- 安装:优先用
go install golang.org/x/tools/gopls@latest安装 gopls,并确认其在 PATH 中;Zed 也会在go可用时自动兜底安装与版本化缓存 gopls。 - 提示与镜头:Zed 默认开启 7 类 gopls 内联提示与
test代码镜头,均可通过lsp.gopls.initialization_options增量覆盖;运行测试的实际命令由 crates/languages/src/go.rs 中的任务模板生成。 - 调试:
.zed/debug.json支持 debug / test / exec 三种常用 launch 模式及直连现有 Delve 的tcp_connection方式;适配器还提供环境变量文件、路径映射、后端选择等进阶字段。 - 生态联动:
.go.mod/.go.work有内置高亮;Templ 场景下可通过 Tailwind CSS 语言服务器获得 HTML 级别的工具类补全。
如果你是 Go 开发并希望把 Zed 作为主力编辑器,建议从新建 .zed/debug.json、放上上面"调试包 / 调试测试"两段最小配置开始,配合 code lens 的 run test 入口即可覆盖绝大多数日常开发与问题排查场景。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00