[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-golangci-lint-faq-ci-policy-zh":3,"article-related-golangci-lint-faq-ci-policy-zh":30,"series-tools-04a7998f-745f-4a4d-851b-d5888aac1000":73},{"id":4,"slug":5,"title":6,"content":7,"summary":8,"source":9,"source_url":10,"author":11,"image_url":12,"cover_image":12,"category":13,"language":14,"translated_content":11,"related_article_id":15,"keywords":16,"key_takeaways":22,"views":26,"created_at":27,"published_at":28,"topic_cluster_id":29},"04a7998f-745f-4a4d-851b-d5888aac1000","golangci-lint-faq-ci-policy-zh","FAQ 把 golangci-lint 變 CI 政策","\u003Cp data-speakable=\"summary\">這篇把 golangci-\u003Ca href=\"\u002Fnews\u002Fgolangci-lint-v2-5-0-revive-checks-zh\">lint\u003C\u002Fa> 的 FAQ 轉成一份可直接抄進 CI 的政策。\u003C\u002Fp>\u003Cp>我用 \u003Ca href=\"https:\u002F\u002Fgolangci-lint.run\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">golangci-lint\u003C\u002Fa> 一陣子了，工具本身其實不難用，難的是你以為它會照你的直覺跑。CI 一接上去，輸出一大坨，我就開始懷疑人生：這到底是 lint 壞掉、編譯壞掉，還是我把它丟進一個根本不能 build 的專案？這種摩擦最煩，因為它不會大爆炸，它只會慢慢把團隊對 gate 的信任磨掉。\u003C\u002Fp>\u003Cp>後來我不是去看宣傳頁，我是去翻 FAQ。結果我才發現，真正有用的不是功能清單，是那些很不討喜但很誠實的限制：Go 版本怎麼對、typecheck 為什麼不能跳過、第一次跑為什麼慢、老專案怎麼不要被舊債淹死。FAQ 讀完，我才意識到它其實是一份政策草稿，只是沒幫你整理好。\u003C\u002Fp>\u003Cp>我這篇就是把那份草稿整理成你可以直接拿去用的版本。原始來源是 \u003Ca href=\"https:\u002F\u002Fgolangci-lint.run\u002Fdocs\u002Fwelcome\u002Ffaq\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">golangci-lint FAQ\u003C\u002Fa>，我不打算把它講得很玄，因為它本來就不是玄學；它只是把 CI 的邊界講清楚而已。\u003C\u002Fp>\u003Ch2>先別幻想它能跟上每個 Go 新版\u003C\u002Fh2>\u003Cblockquote>\u003Cp>“Golangci-lint supports Go versions lower or equal to the Go version used to compile it.”\u003C\u002Fp>\n\u003Cfigure class=\"my-6\">\u003Cimg src=\"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1782607697597-rh2b.png\" alt=\"FAQ 把 golangci-lint 變 CI 政策\" class=\"rounded-xl w-full\" loading=\"lazy\" \u002F>\u003C\u002Ffigure>\n\u003C\u002Fblockquote>\u003Cp>翻譯一下就是：你的 lint binary 不是神，它是拿某個 Go toolchain 編出來的，所以它能支援的 Go 版本有上限。FAQ 還補了一刀，說它的支援策略跟 Go 官方的兩個最新 minor 版本政策一致。也就是說，你如果先把 repo 升到最新 Go，卻沒同步更新 golangci-lint，CI 出怪事不是意外，是你自己在製造版本落差。\u003C\u002Fp>\u003Cp>我看過很多團隊很愛「Go 先升，工具慢慢補」。聽起來很務實，實際上常常是把問題留給 CI。第一個失敗一出來，大家就開始罵 lint 不穩。通常不是不穩，是太舊。工具早就把訊號丟給你了，只是我們不想承認版本組合已經過期。\u003C\u002Fp>\u003Cp>實操寫法很簡單：Go 和 golangci-lint 都要在 CI 裡明確 pin 版本，而且要一起升，不要各自漂。local 開發機跟 build image 也別差太遠，不然你會得到一堆「我本機沒事」的垃圾對話。如果你自己打包 golangci-lint，連它是用哪個 Go 編出來的都要寫進 release notes，不然排錯時大家只會互相甩鍋。\u003C\u002Fp>\u003Cul>\u003Cli>CI 裡固定 Go 版本，不要靠 latest。\u003C\u002Fli>\u003Cli>golangci-lint 版本也固定，不要讓它自己飄。\u003C\u002Fli>\u003Cli>每次升 Go，都把 lint binary 一起驗證。\u003C\u002Fli>\u003C\u002Ful>\u003Cp>這件事我會建議你直接當成政策，不要當成最佳實務。因為一旦你把它寫成政策，團隊就比較不會在「先升再說」這種鬼故事上浪費時間。\u003C\u002Fp>\u003Ch2>typecheck 不是 lint，別硬把編譯錯誤包裝成提醒\u003C\u002Fh2>\u003Cblockquote>\u003Cp>“typecheck is not a linter, it doesn’t perform any analysis, it’s just a way to identify, parse, and display compiling errors.”\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>這句是整份 FAQ 最重要的一句。翻譯一下就是：typecheck 出錯，不代表某個 lint 規則抓到問題，而是你的程式根本還沒到能被分析的狀態。它只是把編譯錯誤顯示出來，沒有任何「我先幫你放水」的空間。\u003C\u002Fp>\u003Cp>FAQ 也講得很直接：只要有 typecheck errors，golangci-lint 就沒辦法產生其他報告。很多人第一次看到只出一個錯，就以為別的 linters 沒跑。不是沒跑，是前面的門都沒過，後面根本沒東西可分析。這很煩，但很合理。\u003C\u002Fp>\u003Cp>我自己最常遇到的是只 lint 部分 package 或某個檔案，結果 typecheck 爆掉。這時候大家第一反應常是「那就忽略它啊」。我懂這個衝動，但這個想法很危險。你一旦把編譯錯誤當成可忽略項，CI 就會開始對不能分析的 code 說「看起來沒事」，那比 noisy output 還糟。\u003C\u002Fp>\u003Cp>實操寫法：先把編譯當成第一關。先跑 \u003Ccode>go build .\u002F...\u003C\u002Fcode>，再期待 lint 的輸出有意義。若有 CGO，就先把系統 library 裝好；若是 private dependency，就先把 \u003Ccode>GOPROXY\u003C\u002Fcode> 與 \u003Ccode>GOSUMDB\u003C\u002Fcode> 設對。你如果只查局部範圍，也要誠實面對那個範圍到底能不能獨立編譯。\u003C\u002Fp>\u003Cul>\u003Cli>先修 build error，再修 lint error。\u003C\u002Fli>\u003Cli>能全模組檢查就別只查片段。\u003C\u002Fli>\u003Cli>typecheck 不是 warning，是前置條件沒過。\u003C\u002Fli>\u003C\u002Ful>\u003Cp>這種分層很重要。你把編譯和 lint 混在一起，最後只會得到一個看似很嚴格、其實很會騙人的 gate。\u003C\u002Fp>\u003Ch2>別想跳過 typecheck，因為那是在跳過入口\u003C\u002Fh2>\u003Cblockquote>\u003Cp>“Why is it not possible to skip\u002Fignore typecheck errors?”\u003C\u002Fp>\n\u003Cfigure class=\"my-6\">\u003Cimg src=\"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1782607697786-sffz.png\" alt=\"FAQ 把 golangci-lint 變 CI 政策\" class=\"rounded-xl w-full\" loading=\"lazy\" \u002F>\u003C\u002Ffigure>\n\u003C\u002Fblockquote>\u003Cp>FAQ 的回答其實就是上一段的延伸：因為 typecheck errors 會擋住分析，所以它不能像一般 lint finding 那樣被忽略。這不是工具小氣，是流程順序本來就這樣。你不能先把門踹開，再要求裡面的房間照常整理。\u003C\u002Fp>\u003Cp>這裡最常見的誤解是把「忽略規則」拿來處理所有問題。那套邏輯只適用於你已經拿到一個有效結果，然後想排除某些已知例外。typecheck 完全不是這種情況。它是在說：這個程式目前不夠完整，後面的分析沒有可靠基礎。\u003C\u002Fp>\u003Cp>我之前跟團隊吵過這件事，對方很想要一個「先讓 broken package 過去」的開關。我不是不能理解，畢竟大家都想先交付。但你如果這樣做，CI 會開始報告「乾淨」，而那個乾淨其實是假的。這種假乾淨最毒，因為它會讓人以為風險不存在。\u003C\u002Fp>\u003Cp>實操寫法：如果你真的需要緩衝，請把 pipeline 切成兩段。第一段只負責證明 code 能編譯；第二段才跑 golangci-lint。若某個區域暫時壞掉，就用明確的 path 或 package 排除，並寫清楚原因。不要把 typecheck 當成一般 lint finding 來處理，這樣只會把問題藏起來。\u003C\u002Fp>\u003Cp>這也是我對 FAQ 最服氣的地方：它沒有假裝能幫你解決所有壞狀況，它只是在提醒你，別拿錯工具處理錯層級的問題。\u003C\u002Fp>\u003Ch2>舊問題太多時，別硬推全量修復\u003C\u002Fh2>\u003Cblockquote>\u003Cp>“The idea is to not fix all existing issues. Fix only newly added issue: issues in new code.”\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>這句其實就是整篇的核心。翻譯一下：如果 repo 裡早就一堆 lint 債，你現在最該做的不是開一場全員修地獄，而是先阻止新的債繼續長大。這才是大多數團隊真的做得到的事。\u003C\u002Fp>\u003Cp>FAQ 建議用 \u003Ccode>--new-from-merge-base=main\u003C\u002Fcode> 或 \u003Ccode>--new-from-rev=HEAD~1\u003C\u002Fcode>。這個方向我完全同意，因為它把 lint 從「一次清完」變成「只管新東西」。我在大 repo 裡推 lint，最後能活下來的幾乎都是這種模式。不是因為它完美，是因為它不會逼大家先停工半年。\u003C\u002Fp>\u003Cp>實操寫法：CI 針對 target branch 的 merge base 來比對，不要只看最後一個 commit。這樣比較能反映真正的變更範圍。如果你是簡單的 commit-based 檢查，就用 \u003Ccode>--new-from-rev=HEAD~1\u003C\u002Fcode>。重點不是你選哪個參數，而是你要明確定義「新 code」是什麼，不然 lint 會變成一個很會吵的歷史清算機。\u003C\u002Fp>\u003Cul>\u003Cli>branch CI 用 \u003Ccode>--new-from-merge-base=main\u003C\u002Fcode>。\u003C\u002Fli>\u003Cli>單 commit 檢查用 \u003Ccode>--new-from-rev=HEAD~1\u003C\u002Fcode>。\u003C\u002Fli>\u003Cli>舊債留在 backlog，不要卡住交付。\u003C\u002Fli>\u003C\u002Ful>\u003Cp>這種做法比較像政策，不像工具設定。差別很大，因為政策是在講團隊怎麼做決定，不是在講某個 flag 長什麼樣。\u003C\u002Fp>\u003Ch2>diff-based 過濾很方便，但它不是語意理解\u003C\u002Fh2>\u003Cblockquote>\u003Cp>“If an issue is not reported as the same line as the changes then the issue will be skipped.”\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>這句很關鍵，因為它直接告訴你：\u003Ccode>--new-from-*\u003C\u002Fcode> 是靠 git diff 和 issue 對齊在運作，不是靠什麼神奇的語意分析。也就是說，如果問題沒有落在變更行上，它就可能被跳過。這不是 bug，這是這套方法的代價。\u003C\u002Fp>\u003Cp>我遇過 refactor 把檔案動了一輪，結果 warning 出現在 diff 之外的區塊，CI 就安靜得像沒事。那種安靜最可怕，因為它不是沒問題，而是你剛好沒看到。人很容易把 automation 的沉默誤認成正確。\u003C\u002Fp>\u003Cp>實操寫法：先用 diff-based new-code lint，夠用就好；但如果你在做大幅重構、搬移 code、或一個 file 裡的問題很容易落在 changed line 之外，就改用 \u003Ccode>--whole-files\u003C\u002Fcode>。FAQ 也有提醒這點：whole-file 會看整個包含變更的檔案，不只看變更行。訊號會變廣，噪音也會變多，但總比漏掉真問題好。\u003C\u002Fp>\u003Cp>我的原則很土：你要的是能抓住你在乎的錯，不是最漂亮的參數組合。只要 diff filter 開始遮住真問題，我就會把範圍放大。別讓工具太聰明，聰明到把你想抓的錯順手放過。\u003C\u002Fp>\u003Ch2>第一次跑很慢，不代表它天生拖累 CI\u003C\u002Fh2>\u003Cblockquote>\u003Cp>“Because the first run caches type information. All subsequent runs will be faster.”\u003C\u002Fp>\u003C\u002Fblockquote>\u003Cp>這句的意思很單純：第一次跑慢，是因為它在做快取。翻譯一下就是，第一輪付的是初始化成本，後面才吃得到 cache 的好處。很多人看到第一次慢，就直接判它死刑，這其實有點冤。\u003C\u002Fp>\u003Cp>我看過有人拿 cold start 來評估 golangci-lint，跑一次就說太慢、太重、太不值得。這種測法很常見，也很不公平。你如果只看第一次，等於拿還沒熱機的車去嫌它油耗差。CI 環境如果每次都重來，那就更需要把 cache 策略想清楚，而不是先怪工具。\u003C\u002Fp>\u003Cp>實操寫法：本機開發時盡量保留 cache，CI 也盡量持久化。不要把 \u003Ccode>--fast-only\u003C\u002Fcode> 當成萬靈丹，然後再抱怨第一次跑很慢。FAQ 很明白地說了，第一次跑會先把 type info cache 起來，這本來就是成本。你要評估的是 warm cache 後的日常表現，不是冷啟動那一下。\u003C\u002Fp>\u003Cp>如果你的 lint 流程是先 lint 再 build，我會建議你調順序。先 build，讓狀態穩定，再 lint。這樣 cache 才真的有機會幫你省時間，不然每次都在\u003Ca href=\"\u002Fnews\u002Fanthropic-mythos-5-reopen-key-points-zh\">重新\u003C\u002Fa>認識同一份 code，當然慢。\u003C\u002Fp>\u003Ch2>客製 lint 可以做，但別把主流程弄成雜物抽屜\u003C\u002Fh2>\u003Cp>FAQ 裡有提到 custom linter 的整合方式：你可以照手冊自己接，也可以開 \u003Ca href=\"\u002Ftag\u002Fgithub\">GitHub\u003C\u002Fa> issue 等維護者有空處理。這聽起來很客氣，但意思其實很明白：能接，不代表\u003Ca href=\"\u002Fnews\u002Frisc-v-mentorships-paid-limited-public-zh\">應該把\u003C\u002Fa>主流程全拿去賭一個特殊需求。\u003C\u002Fp>\u003Cp>翻譯一下就是，golangci-lint 的確可以擴充，但擴充是有成本的。如果你們團隊一直想加一些很私人的規則，我會先問：這個規則真的該放在 lint 層嗎？有些東西適合放在 analyzer，有些其實用獨立 script 更清楚。不要什麼都往同一個工具塞，最後沒人知道是哪條規則在擋 build。\u003C\u002Fp>\u003Cp>我最怕看到 lint config 變成雜物抽屜。今天塞一個 one-off check，明天再塞一個團隊特例，久了之後整份設定像是誰都碰過、誰都不敢刪。FAQ 這裡沒有過度鼓吹客製，我反而覺得這很實在。\u003C\u002Fp>\u003Cp>實操寫法：只有在規則有明確 owner、輸出格式穩定、而且真的會長期用，才把 custom linter 放進主 gate。還在試驗期的東西，先放外面。先讓它證明自己值得被納入，不要一開始就把主流程搞得像實驗室。\u003C\u002Fp>\u003Ch2>可抄的模板\u003C\u002Fh2>\u003Cpre>\u003Ccode># golangci-lint CI policy for Go repos\n# Source: https:\u002F\u002Fgolangci-lint.run\u002Fdocs\u002Fwelcome\u002Ffaq\u002F\n# Related docs: https:\u002F\u002Fgolangci-lint.run\u002F , https:\u002F\u002Fgolangci-lint.run\u002Fdocs\u002Fusage\u002Flinters\u002F\n\npolicy:\n  versioning:\n    go: \"pin in CI\"\n    golangci-lint: \"pin in CI\"\n    rule: \"upgrade Go and golangci-lint together\"\n    note: \"golangci-lint only supports Go versions \u003C= the Go version used to compile it\"\n\n  build_gate:\n    order:\n      - \"go mod tidy\"\n      - \"go build .\u002F...\"\n      - \"golangci-lint run .\u002F...\"\n    rule: \"typecheck errors are build failures, not lint warnings\"\n\n  legacy_debt:\n    rule: \"do not block delivery on pre-existing issues in main\"\n    enforce_only_on_new_code: true\n    commands:\n      branch_ci: \"golangci-lint run --new-from-merge-base=main\"\n      commit_ci: \"golangci-lint run --new-from-rev=HEAD~1\"\n\n  diff_filtering:\n    default: \"diff-based new-code lint\"\n    widen_scope_when:\n      - \"refactor hides issues outside changed lines\"\n      - \"file-level edits miss relevant warnings\"\n    fallback_command: \"golangci-lint run --new-from-merge-base=main --whole-files\"\n\n  performance:\n    expectation: \"first run is slower because type info is cached\"\n    practice:\n      - \"persist cache locally and in CI when possible\"\n      - \"judge speed after warm cache, not cold start\"\n\n  custom_checks:\n    rule: \"keep one-off checks out of the main gate until they have a clear owner and stable purpose\"\n    preferred_path: \"use built-in linters first; add custom linters only when the use case is durable\"\n\nci_statement: |\n  The build must compile cleanly.\n  golangci-lint is enforced only on new code.\n  Legacy issues stay visible but do not block delivery.\n  Typecheck errors are treated as build failures, not lint warnings.\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>這份模板我會直接丟進 repo，然後把 CI command 接好。它不花俏，但它把 FAQ 的重點都收進去了：版本要對齊、先編譯再 lint、只擋新 code、diff filter 不夠時要能放寬、custom check 別亂塞。這才是能長期活下來的寫法。\u003C\u002Fp>\u003Cp>如果要我今天重做一次，我不會再把 golangci-lint 當成一個「跑一下看結果」的工具。我會把它當政策執行器。工具只是工具，真正決定它有沒有價值的，是你有沒有把邊界講清楚。\u003C\u002Fp>\u003Cp>來源是官方 FAQ：\u003Ca href=\"https:\u002F\u002Fgolangci-lint.run\u002Fdocs\u002Fwelcome\u002Ffaq\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">https:\u002F\u002Fgolangci-lint.run\u002Fdocs\u002Fwelcome\u002Ffaq\u002F\u003C\u002Fa>。我這篇的拆解、流程整理和模板是我自己的整理，原始觀點與命令範例則來自該頁面。\u003C\u002Fp>","把 golangci-lint FAQ 拆成可直接套用的 Go CI 政策，重點是版本對齊、先編譯再 lint、只擋新問題。","golangci-lint.run","https:\u002F\u002Fgolangci-lint.run\u002Fdocs\u002Fwelcome\u002Ffaq\u002F",null,"https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1782607697597-rh2b.png","tools","zh","76829ec6-953d-4ae8-8cbd-7d4ebf92ed5f",[17,18,19,20,21],"golangci-lint","CI policy","typecheck","Go lint","new-code-only",[23,24,25],"把 golangci-lint 當成 CI 政策，不要只當 lint 工具。","typecheck 是編譯前置條件，不能當一般 lint error 忽略。","大 repo 用 new-code-only 與 merge-base，比全量清債更能落地。",0,"2026-06-28T00:47:53.937018+00:00","2026-06-28T00:47:53.927+00:00","6706c5ce-71b1-4bef-b28a-28e17a9b0d77",{"tags":31,"relatedLang":32,"relatedPosts":36},[],{"id":15,"slug":33,"title":34,"language":35},"golangci-lint-faq-ci-policy-en","Golangci-lint’s FAQ turns CI noise into a policy","en",[37,43,49,55,61,67],{"id":38,"slug":39,"title":40,"cover_image":41,"image_url":41,"created_at":42,"category":13},"199c5c27-7d55-46b4-a59f-fa2a9d4d6340","gorm-advanced-query-helpers-guardrails-zh","GORM 查詢助手把 SQL 變護欄","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1782606801104-8e4w.png","2026-06-28T00:32:58.617013+00:00",{"id":44,"slug":45,"title":46,"cover_image":47,"image_url":47,"created_at":48,"category":13},"c81b891c-6bd0-48e7-b9b0-eacbc93560f0","golangci-lint-v2-5-0-revive-checks-zh","Golangci-lint v2.5.0 加入 8 項 revive 檢查","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1782605877403-srf2.png","2026-06-28T00:17:31.421555+00:00",{"id":50,"slug":51,"title":52,"cover_image":53,"image_url":53,"created_at":54,"category":13},"7dfeee82-47b0-41bb-8a47-0ad5c9203a23","open-source-ai-projects-developers-2026-zh","2026 開發者必備 7 個開源 AI 專案","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1782593290041-l5h1.png","2026-06-27T20:47:36.429404+00:00",{"id":56,"slug":57,"title":58,"cover_image":59,"image_url":59,"created_at":60,"category":13},"032a0b15-7665-4662-a3e2-ca7d5873f4d0","midjourney-review-2026-v8-worth-it-zh","Midjourney 2026 評測：V8 還值得嗎","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1782576173444-63qz.png","2026-06-27T16:02:30.078028+00:00",{"id":62,"slug":63,"title":64,"cover_image":65,"image_url":65,"created_at":66,"category":13},"12f76440-abb5-4e5f-9b98-d12c7468652d","midjourney-v81-faster-renders-pricing-video-zh","Midjourney V8.1 4-5倍加速上線","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1782573468737-8pyt.png","2026-06-27T15:17:23.186362+00:00",{"id":68,"slug":69,"title":70,"cover_image":71,"image_url":71,"created_at":72,"category":13},"91637501-ee43-4951-b43c-ce2ba3299d3a","mlops-roadmap-2026-turns-learning-into-delivery-zh","MLOps 路線圖把學習變交付","https:\u002F\u002Fxxdpdyhzhpamafnrdkyq.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fcovers\u002Finline-1782567219485-a9wf.png","2026-06-27T13:33:06.891797+00:00",[74,79,84,89,94,99,104,109,114,119],{"id":75,"slug":76,"title":77,"created_at":78},"855cd52f-6fab-46cc-a7c1-42195e8a0de4","surepath-real-time-mcp-policy-controls-zh","SurePath 推出即時 MCP 政策控管","2026-03-26T07:57:40.77233+00:00",{"id":80,"slug":81,"title":82,"created_at":83},"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":85,"slug":86,"title":87,"created_at":88},"af9c46c3-7a28-410b-9f04-32b3de30a68c","prompting-in-2026-what-actually-works-zh","2026 提示工程，真正有用的是什麼","2026-03-26T08:08:12.453028+00:00",{"id":90,"slug":91,"title":92,"created_at":93},"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":95,"slug":96,"title":97,"created_at":98},"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":100,"slug":101,"title":102,"created_at":103},"a5f94120-ac0d-4483-9a8b-63590071ac6a","claude-code-vs-cursor-2026-zh","Claude Code 與 Cursor 深度對比：202…","2026-03-26T13:27:14.279193+00:00",{"id":105,"slug":106,"title":107,"created_at":108},"0975afa1-e0c7-4130-a20d-d890eaed995e","practical-github-guide-learning-ml-2026-zh","2026 機器學習入門 GitHub 實用指南","2026-03-27T01:16:49.712576+00:00",{"id":110,"slug":111,"title":112,"created_at":113},"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":115,"slug":116,"title":117,"created_at":118},"80cabc3e-09fc-4ff5-8f07-b8d68f5ae545","ai-trending-github-repos-and-research-feeds-zh","AI Trending：把 AI 資源收成一張表","2026-03-27T01:31:35.262183+00:00",{"id":120,"slug":121,"title":122,"created_at":123},"3ce6e6e2-bac5-463e-9f8d-45caabcc61f7","awesome-ai-for-science-research-tools-map-zh","AI 科研工具清單，開始像地圖了","2026-03-27T01:46:50.521945+00:00"]