[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-build-language-servers-in-go-without-boilerplate-zh":3,"tags-build-language-servers-in-go-without-boilerplate-zh":33,"related-lang-build-language-servers-in-go-without-boilerplate-zh":49,"related-posts-build-language-servers-in-go-without-boilerplate-zh":53,"series-tools-492a63a6-26d1-41fc-9267-a302acf67f45":90},{"id":4,"title":5,"content":6,"summary":7,"source":8,"source_url":9,"author":10,"image_url":11,"keywords":12,"language":21,"translated_content":10,"views":22,"is_premium":23,"created_at":24,"updated_at":24,"cover_image":11,"published_at":25,"rewrite_status":26,"rewrite_error":10,"rewritten_from_id":27,"slug":28,"category":29,"related_article_id":30,"status":31,"google_indexed_at":32,"x_posted_at":10,"tweet_text":10,"title_rewritten_at":10,"title_original":10,"key_takeaways":10,"topic_cluster_id":10,"embedding":10,"is_canonical_seed":23},"492a63a6-26d1-41fc-9267-a302acf67f45","Go 寫 LSP 少寫一堆樣板","\u003Cp>說真的，這題很實際。\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fowenrumney\u002Fglsp\" target=\"_blank\" rel=\"noopener\">glsp\u003C\u002Fa> 這個 Go 函式庫，直接把 LSP 3.17、handler 自動註冊，還有 debug server 一次包進來。對開發者來說，少寫一堆樣板碼，通常比多一個花俏功能更有感。\u003C\u002Fp>\u003Cp>你可能會想問，為什麼要在意 LSP。因為一套語法提示、診斷、跳轉定義，可以同時送到 \u003Ca href=\"https:\u002F\u002Fcode.visualstudio.com\u002F\" target=\"_blank\" rel=\"noopener\">Visual Studio Code\u003C\u002Fa>、\u003Ca href=\"https:\u002F\u002Fwww.jetbrains.com\u002F\" target=\"_blank\" rel=\"noopener\">JetBrains IDEs\u003C\u002Fa>，還有其他編輯器。不是每個工具都值得做一個完整外掛，但很多工具都值得有編輯器支援。\u003C\u002Fp>\u003Cp>這篇我想講白一點。這不是在吹 protocol 很偉大。重點是，Go 開發者現在多了一條更省事的路，可以把 CLI、Makefile、GoReleaser 這類工具，直接接進編輯器工作流。\u003C\u002Fp>\u003Ch2>glsp 到底在解什麼痛點\u003C\u002Fh2>\u003Cp>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fowenrumney\u002Fglsp\" target=\"_blank\" rel=\"noopener\">glsp\u003C\u002Fa> 的定位很直白。它想讓你用 Go 寫 \u003Ca href=\"\u002Fnews\u002Fxiaomi-mimo-tokenplan-pricing-launch-zh\">lan\u003C\u002Fa>guage server，還不用手動處理太多 protocol 接線。對很多人來說，LSP 最大的痛不是協定本身，而是周邊雜事太多。\u003C\u002Fp>\n\u003Cfigure class=\"my-6\">\u003Cimg src=\"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1775261571145-9urr.png\" alt=\"Go 寫 LSP 少寫一堆樣板\" class=\"rounded-xl w-full\" loading=\"lazy\" \u002F>\u003C\u002Ffigure>\n\u003Cp>像是初始化流程、method dispatch、request response、error handling，這些東西一堆。你本來只是想做 complet\u003Ca href=\"\u002Fnews\u002Fbuild-crypto-ai-agent-bankr-zerion-zh\">ion\u003C\u002Fa>，結果先寫了半天框架。說真的，這種體驗很勸退。\u003C\u002Fp>\u003Cp>glsp 的做法是用 i\u003Ca href=\"\u002Fnews\u002Faustralia-anthropic-ai-safety-mou-zh\">nt\u003C\u002Fa>erface 來自動註冊 handler。你定義 hover、diagnostics、completion 這些功能時，不用自己手動把每個 method 接到 router。這種設計很 Go，也很對味。\u003C\u002Fp>\u003Cul>\u003Cli>支援 \u003Ca href=\"https:\u002F\u002Fmicrosoft.github.io\u002Flanguage-server-protocol\u002Fspecifications\u002Flsp\u002F3.17\u002Fspecification\u002F\" target=\"_blank\" rel=\"noopener\">LSP 3.17\u003C\u002Fa>\u003C\u002Fli>\u003Cli>handler 可以自動註冊\u003C\u002Fli>\u003Cli>內建 debug server\u003C\u002Fli>\u003Cli>已有 \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fowenrumney\u002Fmake-ls\" target=\"_blank\" rel=\"noopener\">Makefile\u003C\u002Fa> 範例\u003C\u002Fli>\u003Cli>也有 \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fowenrumney\u002Fgoreleaser-ls\" target=\"_blank\" rel=\"noopener\">GoReleaser\u003C\u002Fa> 範例\u003C\u002Fli>\u003C\u002Ful>\u003Cp>這些例子很有意思。因為它們不是教科書案例，而是日常會碰到的檔案。Makefile、CI 設定、發版腳本，這些東西常常沒人想寫完整 IDE 外掛，但又很需要提示和檢查。\u003C\u002Fp>\u003Cp>我覺得這就是 glsp 的價值。它不是要你重做一個 IDE。它是讓你把既有工具，補上編輯器那一層。\u003C\u002Fp>\u003Ch2>為什麼自動註冊這件事很重要\u003C\u002Fh2>\u003Cp>很多 framework 都會說自己很簡潔。真正用下去才知道，簡潔常常只是把複雜藏起來。glsp 比較討喜的地方，是它把 wiring 縮到很小，而且還保留 Go 的明確感。\u003C\u002Fp>\u003Cp>在 Hacker News 的討論裡，有人直接稱讚這種 interface-based auto-registration pattern。這不是空話。因為在 LSP 這種場景，手動接線越多，越容易漏 method，或是加功能時改到一半忘記掛上去。\u003C\u002Fp>\u003Cp>作者也提到一個很現實的行為差異。handler 回傳一般 error 時，server 會送 error response，然後繼續跑。可是如果 handler panic，server 會直接掛掉。這種細節很重要，因為它決定了你敢不敢把它放進真實專案。\u003C\u002Fp>\u003Cblockquote>“That’s the kind of API design that makes Go’s implicit interfaces shine.”\u003C\u002Fblockquote>\u003Cp>這句來自 HN 討論。講得很準。Go 的 implicit interface 本來就適合做這種事。你不用先註冊一長串表格，只要把方法做對，框架就能抓到。\u003C\u002Fp>\u003Cp>另外，debug server 也很實用。LSP 的 bug 常常不是語法錯，而是訊息在 editor、server、parser 之間轉錯。能直接看訊息流，排錯時間會少很多。這不是炫技，是救命。\u003C\u002Fp>\u003Ch2>跟其他 LSP 工具比，差在哪\u003C\u002Fh2>\u003Cp>Go 世界裡不是只有 glsp。作者自己也提到，他一開始是從 \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ftliron\u002Fglsp\" target=\"_blank\" rel=\"noopener\">tliron\u002Fglsp\u003C\u002Fa> 起步。後來自己做一套，主要是想要 debug UI 和更順手的開發體驗。\u003C\u002Fp>\n\u003Cfigure class=\"my-6\">\u003Cimg src=\"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1775261574792-e75c.png\" alt=\"Go 寫 LSP 少寫一堆樣板\" class=\"rounded-xl w-full\" loading=\"lazy\" \u002F>\u003C\u002Ffigure>\n\u003Cp>這點很像很多工程團隊的真實選擇。不是原本工具不好，而是它不合你的工作流。你如果每天都在看 message flow，沒有 debug 視圖真的很痛。\u003C\u002Fp>\u003Cp>如果把幾個方案放在一起看，差異就比較清楚。LSP 本身是標準，但實作體驗差很多。下面這幾點，會直接影響你會不會真的把它用進產品。\u003C\u002Fp>\u003Cul>\u003Cli>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ftliron\u002Fglsp\" target=\"_blank\" rel=\"noopener\">tliron\u002Fglsp\u003C\u002Fa> 是既有選項\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fowenrumney\u002Fglsp\" target=\"_blank\" rel=\"noopener\">owenrumney\u002Fglsp\u003C\u002Fa> 主打 debug-first 工作流\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fcode.visualstudio.com\u002Fapi\u002Flanguage-extensions\u002Flanguage-server-extension-guide\" target=\"_blank\" rel=\"noopener\">VS Code LSP 指南\u003C\u002Fa> 顯示 protocol 重用的好處\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fmicrosoft.github.io\u002Flanguage-server-protocol\u002F\" target=\"_blank\" rel=\"noopener\">LSP\u003C\u002Fa> 能讓不同編輯器共用同一套邏輯\u003C\u002Fli>\u003Cli>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fbbkane\u002Fwarg\" target=\"_blank\" rel=\"noopener\">warg\u003C\u002Fa> 也被討論到可加上 LSP\u003C\u002Fli>\u003C\u002Ful>\u003Cp>如果你做的是 CLI 或內部工具，這個比較就更有意思。你不一定需要完整 GUI，但你很可能需要 hover、completion、diagnostics。這些功能一旦做進去，使用者會覺得你的工具比較像「活的」。\u003C\u002Fp>\u003Cp>我自己的判斷很直接。glsp 這類工具的競爭點，不是誰支援更多行為，而是誰讓你更快做出能上線的 server。對團隊來說，少一週樣板碼，通常比多十個抽象更有價值。\u003C\u002Fp>\u003Ch2>數據和競品角度怎麼看\u003C\u002Fh2>\u003Cp>如果只看 HN 討論熱度，這篇有 92 points。這數字不算炸裂，但足夠說明一件事：開發者對「少寫 LSP 樣板」是有感的。尤其是做 Go 的人，對這種簡潔 API 特別挑剔。\u003C\u002Fp>\u003Cp>再看使用場景。Makefile、GoReleaser、YAML、Terraform、內部 DSL，這些東西都很適合 LSP。因為它們常常有固定結構，卻又很難靠純文字編輯保證正確。編輯器幫你檢查，會比事後 CI 才報錯舒服很多。\u003C\u002Fp>\u003Cp>下面這種比較方式比較務實。不是看誰名氣大，而是看誰比較適合落地。很多工具最後卡住，不是功能不夠，而是整合成本太高。\u003C\u002Fp>\u003Cul>\u003Cli>手動寫 editor plugin：每個編輯器都要重做一次\u003C\u002Fli>\u003Cli>用 LSP：一套 server，多個 editor 共用\u003C\u002Fli>\u003Cli>用 glsp：少掉不少 handler wiring\u003C\u002Fli>\u003Cli>用傳統 framework：可能更成熟，但 debug 體驗不一定順\u003C\u002Fli>\u003Cli>對 CLI 工具來說：補 LSP 往往比加更多 flag 更有感\u003C\u002Fli>\u003C\u002Ful>\u003Cp>這裡還有一個很現實的比較。VS Code、JetBrains、Neovim、Emacs 都能吃 LSP。你如果自己寫插件，維護成本會很高。你如果把重點放在 server，整體成本通常低很多。\u003C\u002Fp>\u003Cp>所以 glsp 的意義，不只是「又多一個 Go library」。它是把 LSP 的進場門檻再往下壓一點。對想把工具做成編輯器友善的團隊，這很有吸引力。\u003C\u002Fp>\u003Ch2>Go 為什麼很適合做這類工具\u003C\u002Fh2>\u003Cp>Go 做工具鏈，本來就很順。編譯快、部署單檔、標準函式庫夠用。對 language server 這種長駐服務來說，這些特性都很實際，不是口號。\u003C\u002Fp>\u003Cp>更重要的是，Go 的 interface 很適合拿來做 handler discovery。你不用搞太多魔法，也不用把整個系統做得很黑盒。對維護者來說，這很重要，因為 LSP 已經夠複雜了。\u003C\u002Fp>\u003Cp>從產業角度看，這種工具會越來越常見。原因很簡單。很多團隊不是沒有工具，而是工具只活在 CLI。只要把 editor support 補上去，使用者感受就差很多。\u003C\u002Fp>\u003Cp>這也是為什麼像 \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fowenrumney\u002Fmake-ls\" target=\"_blank\" rel=\"noopener\">Makefile LSP\u003C\u002Fa> 這種東西會有存在感。它不是做一個新語言，而是把老工具變得比較好用。老實說，這種改造常常比新框架更有價值。\u003C\u002Fp>\u003Cp>我會怎麼看這波。若 glsp 持續把 panic handling、debug 視圖和文件補齊，它很可能會吸引更多 Go-heavy 團隊試用。尤其是那些已經有 parser、validator、CLI 的專案，接 LSP 的成本會比重寫一個 editor plugin 低很多。\u003C\u002Fp>\u003Ch2>接下來最值得看的事\u003C\u002Fh2>\u003Cp>我覺得接下來最值得觀察的，不是 glsp 會不會變成最大宗方案，而是有多少工具會開始把 LSP 當成標配。當 CLI、設定檔、內部 DSL 都能快速接上 editor 支援，開發者體驗會更完整。\u003C\u002Fp>\u003Cp>如果你現在在做 Go 工具，我會直接問一句：你是想再加一個 flag，還是想讓使用者直接在編輯器裡看到診斷和 completion。很多情況下，答案其實很明顯。\u003C\u002Fp>\u003Cp>講白了，這類 library 的價值在於省時間。不是省一點，是省掉一整段重工。對團隊來說，這種省法通常比任何漂亮 demo 都更有說服力。\u003C\u002Fp>\u003Cp>如果你手上有 CLI、Makefile 工具，或任何結構化文字格式，我會建議你真的試一次 LSP。先把最常見的 2 到 3 個功能做出來。像 hover、diagnostics、jump to definition，就很夠用了。\u003C\u002Fp>","一個 Go LSP 函式庫主打 LSP 3.17、handler 自動註冊和 debug server。對想把 CLI、Makefile、YAML 做進編輯器的開發者，這種設計很實用。","news.ycombinator.com","https:\u002F\u002Fnews.ycombinator.com\u002Fitem?id=47510005",null,"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1775261571145-9urr.png",[13,14,15,16,17,18,19,20],"Go","LSP","language server","glsp","editor integration","Visual Studio Code","JetBrains","API","zh",1,false,"2026-04-04T00:12:36.672297+00:00","2026-04-04T00:12:36.585+00:00","done","b9d4aad4-fcb1-427e-829a-4f6ed7489ea5","build-language-servers-in-go-without-boilerplate-zh","tools","4d82e908-1cbb-4b7b-b081-be9074cf846c","published","2026-04-07T07:41:08.504+00:00",[34,35,37,39,41,43,45,47],{"name":16,"slug":16},{"name":18,"slug":36},"visual-studio-code",{"name":14,"slug":38},"lsp",{"name":13,"slug":40},"go",{"name":19,"slug":42},"jetbrains",{"name":15,"slug":44},"language-server",{"name":17,"slug":46},"editor-integration",{"name":20,"slug":48},"api",{"id":30,"slug":50,"title":51,"language":52},"build-language-servers-in-go-without-boilerplate-en","Build language servers in Go without the boilerplate","en",[54,60,66,72,78,84],{"id":55,"slug":56,"title":57,"cover_image":58,"image_url":58,"created_at":59,"category":29},"d058a76f-6548-4135-8970-f3a97f255446","why-gemini-api-pricing-is-cheaper-than-it-looks-zh","為什麼 Gemini API 定價其實比看起來更便宜","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1778869845081-j4m7.png","2026-05-15T18:30:25.797639+00:00",{"id":61,"slug":62,"title":63,"cover_image":64,"image_url":64,"created_at":65,"category":29},"68e4be16-dc38-4524-a6ea-5ebe22a6c4fb","why-vidhub-huiyuan-hutong-bushi-quan-shebei-tongyong-zh","為什麼 VidHub 會員互通不是「買一次全設備通用」","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1778789450987-advz.png","2026-05-14T20:10:24.048988+00:00",{"id":67,"slug":68,"title":69,"cover_image":70,"image_url":70,"created_at":71,"category":29},"7a1e174f-746b-4e82-a0e3-b2475ab39747","why-buns-zig-to-rust-experiment-is-right-zh","為什麼 Bun 的 Zig-to-Rust 實驗是對的","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1778767879127-5dna.png","2026-05-14T14:10:26.886397+00:00",{"id":73,"slug":74,"title":75,"cover_image":76,"image_url":76,"created_at":77,"category":29},"e742fc73-5a65-4db3-ad17-88c99262ceb7","why-openai-api-pricing-is-product-strategy-zh","為什麼 OpenAI API 定價是產品策略，不是註腳","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1778749859485-chvz.png","2026-05-14T09:10:26.003818+00:00",{"id":79,"slug":80,"title":81,"cover_image":82,"image_url":82,"created_at":83,"category":29},"c757c5d8-eda9-45dc-9020-4b002f4d6237","why-claude-code-prompt-design-beats-ide-copilots-zh","為什麼 Claude Code 的提示設計贏過 IDE Copilot","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1778742645084-dao9.png","2026-05-14T07:10:29.371901+00:00",{"id":85,"slug":86,"title":87,"cover_image":88,"image_url":88,"created_at":89,"category":29},"4adef3ab-9f07-4970-91cf-77b8b581b348","why-databricks-model-serving-is-right-default-zh","為什麼 Databricks Model Serving 是生產推論的正確預設","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1778692245329-a2wt.png","2026-05-13T17:10:30.659153+00:00",[91,96,101,106,111,116,121,126,131,136],{"id":92,"slug":93,"title":94,"created_at":95},"de769291-4574-4c46-a76d-772bd99e6ec9","googles-biggest-gemini-launches-in-2026-zh","Google 2026 最大 Gemini 盤點","2026-03-26T07:26:39.21072+00:00",{"id":97,"slug":98,"title":99,"created_at":100},"855cd52f-6fab-46cc-a7c1-42195e8a0de4","surepath-real-time-mcp-policy-controls-zh","SurePath 推出即時 MCP 政策控管","2026-03-26T07:57:40.77233+00:00",{"id":102,"slug":103,"title":104,"created_at":105},"9b19ab54-edef-4dbd-9ce4-a51e4bae4ebb","mcp-in-2026-the-ai-tool-layer-teams-use-zh","2026 年 MCP：團隊真的在用的 AI 工具層","2026-03-26T08:01:46.589694+00:00",{"id":107,"slug":108,"title":109,"created_at":110},"af9c46c3-7a28-410b-9f04-32b3de30a68c","prompting-in-2026-what-actually-works-zh","2026 提示工程，真正有用的是什麼","2026-03-26T08:08:12.453028+00:00",{"id":112,"slug":113,"title":114,"created_at":115},"05553086-6ed0-4758-81fd-6cab24b575e0","garry-tan-open-sources-claude-code-toolkit-zh","Garry Tan 開源 Claude Code 工具包","2026-03-26T08:26:20.068737+00:00",{"id":117,"slug":118,"title":119,"created_at":120},"042a73a2-18a2-433d-9e8f-9802b9559aac","github-ai-projects-to-watch-in-2026-zh","2026 必看 20 個 GitHub AI 專案","2026-03-26T08:28:09.619964+00:00",{"id":122,"slug":123,"title":124,"created_at":125},"a5f94120-ac0d-4483-9a8b-63590071ac6a","claude-code-vs-cursor-2026-zh","Claude Code 與 Cursor 深度對比：202…","2026-03-26T13:27:14.279193+00:00",{"id":127,"slug":128,"title":129,"created_at":130},"0975afa1-e0c7-4130-a20d-d890eaed995e","practical-github-guide-learning-ml-2026-zh","2026 機器學習入門 GitHub 實用指南","2026-03-27T01:16:49.712576+00:00",{"id":132,"slug":133,"title":134,"created_at":135},"bfdb467a-290f-4a80-b3a9-6f081afb6dff","aiml-2026-student-ai-ml-lab-repo-review-zh","AIML-2026：像課綱的學生實驗 Repo","2026-03-27T01:21:51.467798+00:00",{"id":137,"slug":138,"title":139,"created_at":140},"80cabc3e-09fc-4ff5-8f07-b8d68f5ae545","ai-trending-github-repos-and-research-feeds-zh","AI Trending：把 AI 資源收成一張表","2026-03-27T01:31:35.262183+00:00"]