2026-01-18 08:38:57

本文永久链接 – https://tonybai.com/2026/01/18/traits-of-a-good-tech-lead
大家好,我是Tony Bai。
在 2010-2020 这十年间,软件行业逐渐确立了 Engineering Manager (EM) 和 Tech Lead (TL) 这两个关键角色。然而,即便在今天,很多团队对于这两个角色的职责边界依然模糊不清。
究竟什么是 Tech Lead?它和 EM 有什么区别?一个优秀的 TL 应该具备哪些特征?
资深工程主管 João Alves 在他最新的博文中,为我们提供了一份清晰的答案。这是一份包含角色定义的、关于如何通过技术领导力驱动团队高效运转的实战指南。

首先,让我们厘清这两个角色的核心差异。João 认为,虽然两者都服务于团队,但关注点截然不同:

如果用韦恩图来表示,两者的交集在于:团队自治、范围/债务谈判、操作原则和团队成长。在后 ZIRP(零利率政策)时代,追求效率的趋势让这两个角色有时会由一人兼任,但这需要极高的平衡技巧。

一个真正称职的 TL,不一定是写代码最快的人,但却应该是团队的乘数因子 (Multiplier)。João 将 TL 的职责拆解为三个具体的维度,并列举了“加分行为”与“减分行为”。
TL 不必亲手设计每一个细节,但必须掌控系统的整体方向。
TL 需要在“完美技术”与“业务价值”之间寻找平衡点。
这是 TL 提升团队速度的秘密武器。与其事必躬亲,不如建立原则。
如何判断一个 TL 是否成功?不是看他写了多少代码,也不是看他开了多少会。
João 提出了一个极其深刻的衡量标准:随着时间的推移,团队对你的依赖是否在减少?
那么,你就是一个成功的 Tech Lead。反之,如果你成为了团队中最忙碌的瓶颈,无论你的技术有多强,你可能正在偏离 TL 的核心价值。
Tech Lead 是一个充满挑战的角色,它要求工程师走出单纯的代码世界,去思考系统、去影响他人、去建立标准。
无论你是正在转型 TL 的资深工程师,还是与 TL 紧密合作的管理者,理解这份职责清单,都将帮助你们更好地协作,共同打造一支技术卓越、运转高效的工程团队。
资料链接:https://world.hey.com/joaoqalves/traits-of-a-good-tech-lead-b5cac0ae
你的 TL 印象
Tech Lead 是团队的技术灵魂。在你合作过的 Tech Lead 中,哪一种行为最让你觉得“靠谱”?或者,作为 TL 的你,目前面临的最大挑战是什么?(是技术决策难,还是与人沟通累?)
欢迎在评论区分享你的经历或困惑!让我们一起探索技术领导力的进阶之路。
如果这篇文章帮你理清了职业发展的方向,别忘了点个【赞】和【在看】,并转发给你的团队伙伴,也许能开启一场关于角色的深度对话!
还在为“复制粘贴喂AI”而烦恼?我的新专栏 《AI原生开发工作流实战》 将带你:
扫描下方二维码,开启你的AI原生开发之旅。

你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?
继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!
我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。
目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

© 2026, bigwhite. 版权所有.
2026-01-18 08:36:12

本文永久链接 – https://tonybai.com/2026/01/18/go-cryptography-principles
大家好,我是Tony Bai。
在软件工程领域,密码学(Cryptography)通常被视为“高危禁区”。大多数语言的建议都是“不要自己写密码学代码”,甚至“不要自己组合密码学原语”。
然而,Go 语言打破了这一魔咒。Go 的标准库 crypto/… 以及扩展库 golang.org/x/crypto/… 被公认为业界最安全、最易用的密码学实现之一。这并非巧合,而是源于 Go 官方制定并严格遵守的一套《密码学设计原则》。
这份由前 Go 安全负责人 Filippo Valsorda 撰写的文档,确立了四个核心支柱,按优先级排序依次为:Secure(安全)、Safe(稳健)、Practical(实用)和 Modern(现代)。
今天,我们深入解读这四大原则,并结合代码示例,看 Go 是如何将这些原则转化为代码的。

定义: 库的实现本身必须没有安全漏洞。
这听起来像是废话,但在密码学中,”没有漏洞”不仅仅意味着逻辑正确,还意味着要防御侧信道攻击(Side-Channel Attacks)。Go 团队为了达成这一目标,宁愿牺牲一部分性能,也要保证实现的低复杂度和高可读性。
攻击者可以通过测量函数执行的时间长短来推测密钥信息。为了防御时序攻击,Go 在 crypto/subtle 包中提供了恒定时间(Constant-time)操作原语。
示例代码:
在验证 HMAC 签名或哈希时,绝不能使用普通的 == 或 bytes.Equal,因为它们一旦发现字节不匹配就会返回,导致耗时不同。Go 提供了 subtle.ConstantTimeCompare。
// https://go.dev/play/p/TJkuUTcv9Ta
package main
import (
"crypto/hmac"
"crypto/sha256"
"crypto/subtle"
"fmt"
)
func CheckMAC(message, messageMAC, key []byte) bool {
mac := hmac.New(sha256.New, key)
mac.Write(message)
expectedMAC := mac.Sum(nil)
// ❌ 错误做法:return string(messageMAC) == string(expectedMAC)
// 这种比较会因不匹配位置的不同而耗时不同,泄露信息。
// ✅ 符合 Secure 原则的做法:
// 无论内容如何,执行时间恒定,杜绝时序攻击。
return subtle.ConstantTimeCompare(messageMAC, expectedMAC) == 1
}
func main() {
key := []byte("secret-key")
msg := []byte("hello world")
// 假设这是收到的签名
mac := []byte{0xde, 0xad, 0xbe, 0xef}
if CheckMAC(msg, mac, key) {
fmt.Println("Valid")
} else {
fmt.Println("Invalid")
}
}
定义: 库不仅要“可以”被安全使用,更要“难以”被不安全地使用。
这是 Go 密码学库最令人称道的地方。原则指出:默认行为必须是安全的,任何不安全的功能如果必须存在,必须在 API 命名上进行显式确认。
在很多语言中,关闭 HTTPS 证书校验可能只是一个布尔值 verify=false,这容易被开发者在调试后遗忘。但在 Go 的 crypto/tls 中,要跳过证书校验,你必须设置一个名字“长得吓人”的字段:InsecureSkipVerify。
示例代码:
// https://go.dev/play/p/aq2RARNHCgo
package main
import (
"crypto/tls"
"net/http"
)
func main() {
// 默认情况下,http.Client 会严格校验服务端证书,这是“Safe”的默认行为。
// 如果你非要关闭校验(例如自签名证书测试),你必须显式写出 "Insecure"(不安全)这个词。
tr := &http.Transport{
TLSClientConfig: &tls.Config{
// ✅ 符合 Safe 原则的做法:
// 强迫开发者在代码中承认“我在做不安全的事”。
// 这在代码审查时非常显眼。
InsecureSkipVerify: true,
},
}
client := &http.Client{Transport: tr}
_, _ = client.Get("https://self-signed.badssl.com/")
}
此外,Go 的 crypto/rsa 包在加密时,必须传入随机数生成器(io.Reader),这强迫用户思考随机源的问题,而不是在库内部悄悄使用伪随机数。
定义: 专注于解决大多数开发者的常见需求,而非学术研究或冷门场景。
Go 的目标是构建应用程序,而不是密码学测试工具。因此,Go 标准库会拒绝那些并未广泛采用的算法,优先支持互操作性强的标准。
存储用户密码是 Web 开发最常见的需求。Go 在扩展库中直接提供了 bcrypt 包,这是一个久经考验的、针对密码存储优化的算法。它隐藏了盐(Salt)的生成和管理细节,提供了一个极其简单的接口。
示例代码:
// https://go.dev/play/p/BWg0HHxwBso
package main
import (
"fmt"
"golang.org/x/crypto/bcrypt"
)
func main() {
password := []byte("mySuperSecretPassword123")
// ✅ 符合 Practical 原则的做法:
// 开发者不需要懂“加盐”、“迭代次数”等细节,
// GenerateFromPassword 会自动生成随机盐并包含在结果中。
hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
if err != nil {
panic(err)
}
fmt.Println("Hash:", string(hashedPassword))
// 验证也同样简单
err = bcrypt.CompareHashAndPassword(hashedPassword, password)
if err == nil {
fmt.Println("Password match")
}
}
Go 没有强迫开发者去组合 SHA256 和 Salt,而是提供了一个实用、完整的解决方案。
定义: 提供当下最好的工具,并及时淘汰过时的技术。
“现代”不代表“实验性”。Go 会在算法成熟并被广泛接受后迅速跟进,同时对老旧算法(如 RC4、DES)标记为“弃用”(Deprecated)。
当移动设备崛起,且 AES 在无硬件加速(AES-NI)的设备上性能不佳时,Go 迅速在标准库和扩展库中引入了 ChaCha20-Poly1305 流加密算法和 Ed25519 签名算法。它们不仅速度快,而且比 RSA/AES 更难用错。
示例代码:使用 Ed25519 进行签名
Ed25519 是现代公钥签名的杰出代表,它不需要在签名时传入随机数源(避免了索尼 PS3 私钥泄露那样的随机数重用灾难),且公钥极其短小。
// https://go.dev/play/p/W9kRS6Ipm2h
package main
import (
"crypto/ed25519"
"crypto/rand"
"fmt"
)
func main() {
// ✅ 符合 Modern 原则的做法:
// 引入现代、高性能、难以误用的算法。
// Ed25519 生成密钥极快,且签名过程是确定性的,不需要随机数源。
publicKey, privateKey, _ := ed25519.GenerateKey(rand.Reader)
message := []byte("Go is modern")
// 签名
signature := ed25519.Sign(privateKey, message)
// 验证
isValid := ed25519.Verify(publicKey, message, signature)
fmt.Printf("Signature Valid: %v\n", isValid)
}
值得一提的是,Go 在后量子密码学(Post-Quantum Cryptography, PQC)的支持上也走在了前列。
随着 NIST 标准化流程的推进,Go 迅速在标准库(Go 1.24+)中引入了 crypto/mlkem 包,支持 ML-KEM(即 Kyber)密钥封装机制。
更符合 Modern 原则的是,Go 的 crypto/tls 在握手过程中默认启用了 X25519Kyber768Draft00 混合密钥交换。这意味着,开发者往往无需修改一行代码,现有的 Go 应用就已经具备了防御未来量子计算机攻击的能力。这种“静默升级”正是 Go 密码学库现代化的最佳注脚。
Go 的密码学库之所以强大,是因为它懂得克制。
对于 Go 开发者而言,最重要的一条建议是:信任标准库,不要自己造轮子。 因为标准库背后的这些原则,是你应用安全最坚实的护盾。
参考资料:https://golang.org/design/cryptography-principles
你的“加密”故事
密码学的坑,踩过一次就终身难忘。在你的开发生涯中,是否遇到过因为误用加密算法而导致的安全事故?或者,你对 Go 这种“保姆式”的 API 设计有什么看法?
欢迎在评论区分享你的“血泪史”或设计心得! 让我们一起构建更安全的数字世界。
如果这篇文章让你对 Go 的安全性有了更深的理解,别忘了点个【赞】和【在看】,并转发给你的团队,安全无小事!
还在为“复制粘贴喂AI”而烦恼?我的新专栏 《AI原生开发工作流实战》 将带你:
扫描下方二维码,开启你的AI原生开发之旅。

你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?
继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!
我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。
目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

© 2026, bigwhite. 版权所有.
2026-01-17 07:42:05

本文永久链接 – https://tonybai.com/2026/01/17/ai-era-cognitive-friction-as-your-last-moat
大家好,我是Tony Bai。
我们正在经历一场前所未有的知识通胀。
在 AI 时代,获取答案的成本已经降到了零。遇到 Bug?粘贴报错给 AI。写不出周报?给个主题让 AI 生成。想学新框架?让 AI 总结核心概念。
一切都变得无比丝滑,无比高效。
但你有没有发现,在这种“顺滑”的表象下,一种隐秘的症状正在蔓延:
《纽约时报》畅销书《五种财富》的作者Sahil Bloom 将这种症状称为 “AI Brain”(AI 大脑)。
这并不是说你变笨了,而是说你变钝了(Dull)。
就像一个长期坐轮椅的人,腿部肌肉必然会萎缩。当我们习惯了 AI 这种“认知轮椅”,我们大脑中负责深度思考、构建逻辑、处理混乱的那些神经连接,正在慢慢断开。
AI 消除了“摩擦”,但人类的智慧,恰恰诞生于“摩擦”之中。

我们一直被教育要追求效率,要消除阻力。但在认知科学领域,这个逻辑是反的。
真正的学习和创造,发生于“First-pass Thinking”(第一遍思考)的挣扎中。
当你面对一个复杂的架构难题抓耳挠腮时,当你面对一张白纸试图构建文章结构感到挫败时,请珍惜这种痛苦。
这正是你的大脑在“举铁”,神经突触正在高强度地建立新的连接。这种不适感,是你正在突破认知边界的信号。
如果你在这个时刻按下了 AI 的生成键,它确实给了你一个完美的答案,就像剥好了的送到嘴边的虾肉。但你失去了什么?
你失去了咀嚼、消化、甚至感受饥饿的机会。你跳过了“构建心理模型”的过程,直接快进到了结果。
外包了痛苦,也就外包了成长的机会。
那么,我们该如何对抗这种“认知萎缩”?并不是要扔掉 AI 回归原始,而是要主动设计“认知摩擦”。
Sahil Bloom 基于个人洞察,为我们总结了 4 条适合技术人的自救法则:
原则: I write before I refine.(先写再润色,而不是先生成再修改。)
不要一上来就让 AI 写代码或写草稿。
强迫自己写出那个烂透了的初稿,强迫自己先在白板上画出架构图的草图。
因为 AI 只能基于概率生成“平均值”,只有你的“第一遍思考”才带有“方差”——也就是你的原创性(Originality)和个性。
下次写文档,不妨先自己写 300 字的大纲,再让 AI 补充;而不是让 AI 生成大纲,你来修改。
原则: I sit with problems.(让问题飞一会儿。)
遇到难题,不要通过条件反射式地 Alt+Tab 切到 与大模型聊天的页面。
允许自己困惑,允许自己焦虑,允许自己在那里发呆 10 分钟。
这种“滞后”是必要的。它给了你的大脑后台进程运行的时间(思考脑启动)。很多深刻的洞察,往往是在你“卡住”的时候涌现的。
不妨设定一个“无 AI 时间窗口”。比如每天上午的头 2 小时,强制断开 AI 助手,只靠自己的大脑工作。
原则: One kick 10,000 times.(不怕千招会,只怕一招精。)
AI 让我们能做 100 件事:能写前端、能写后端、能画图、能剪视频。但每件事我们都只能做到 60 分的平庸水平。
既然 AI 把广度的成本降到了零,那么深度就成了唯一的护城河。
试试利用 AI 帮你处理那些琐碎的、低认知的杂事,然后把节省下来的精力,全部投入到那个 1% 的核心领域中去。钻研到连 AI 都无法回答的深度。
原则: Stay anchored.(保持锚定。)
AI 没有身体,没有痛感,没有疲惫。
人类的直觉、审美和同理心,建立在我们肉身的经验之上,这是 AI 永远无法模拟的底色。
动起来!去面对面交流,去感受代码运行在真实物理设备上的延迟,去用身体感受世界。这些“肉身经验”是你作为人类的最后防线。
我们正在进入一个“分化”的时代。
区别在于边界的划分。
Your future is defined by what you refuse to let AI do.
(你的未来,取决于你拒绝让 AI 做什么。)
请守住你的“思考领地”。
我可以让 AI 帮我优化代码,但我决不允许它替我设计架构;
我可以让 AI 帮我润色文字,但我决不允许它替我定义观点。
在这个充满“灰度”和“平庸”的 AI 生成世界里,请保持你大脑的“色彩”和“锋利(Sharp)”。
Don’t become dull.
你的“戒断”计划
读完这篇文章,你是否也意识到了自己对 AI 的过度依赖?如果让你现在关掉 AI 助手,你能独立完成手头的工作吗?你打算如何找回自己的“认知摩擦”?
欢迎在评论区立下你的 Flag,或者分享你的“人机边界”思考!让我们一起守护大脑的锋利。
如果这篇文章戳中了你的痛点,别忘了点个【赞】和【在看】,并转发给身边那些“沉迷 AI”的朋友,给他们提个醒!
深度实战:构建“以人为本”的 AI 工作流
在 AI 原生开发中,我们同样强调:User 必须是机长,AI 只是副驾驶。
如何在利用 AI 提效的同时,还能迫使自己进行深度的架构思考?
如何在 Spec-Driven Development (SDD) 中,保留人类的“第一遍思考”权利,让 AI 只做执行者?
欢迎关注我的极客时间专栏《AI原生开发工作流实战》。
在这里,我们不教你如何偷懒,我们教你如何利用 AI 进行更高维度的认知进化。
扫描下方图片二维码,开启你的进化之旅。

你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?
继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!
我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。
目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

© 2026, bigwhite. 版权所有.
2026-01-17 07:38:52

本文永久链接 – https://tonybai.com/2026/01/17/go-rust-zig-simplicity-vs-control
大家好,我是Tony Bai。
在系统编程的世界里,开发者似乎总是面临着一个残酷的二选一:是选择极致的简单与生产力,还是选择绝对的控制与零成本抽象?
这种纠结在 Go 与 Rust 的长期对峙中体现得淋漓尽致。然而,近日一位拥有十年 Go 经验的资深开发者在Zig社区的分享,似乎为这场二元对立的战争撕开了一道口子。他从 Go 迁移到 Zig 的经历,既是一个技术选型的故事,也是一场关于“我们到底需要什么样的编程语言”的深度辩论。

对于许多 Gopher 来说,Go 的简单是其最大的武器,但也是最深的痛点。
这位楼主坦言,尽管他深爱 Go 的简单,但在编写某些复杂系统时,这种“过度简化”让他感觉语言本身存在缺陷。
如果嫌 Go 太简单,Rust 似乎是理所当然的替代者。但对于很多习惯了 Go “写完即运行”体验的开发者来说,Rust 的门槛是一堵高墙。
楼主表示,他喜欢 Rust 的核心概念(Structs, Enums, Option),但 Rust 为了内存安全而引入的借用检查器、生命周期以及复杂的异步模型,让他感觉“像是面对另一个 C++”。
这是一场灵魂拷问:为了获得控制权,我们真的需要背负如此沉重的认知包袱吗?
Zig 的出现,似乎精准地击中了 Go 与 Rust 之间的那个真空地带。对于这位 Gopher 来说,Zig 让他感到了久违的“刚刚好”:
当然,这场灵魂拷问没有标准答案。社区的讨论也极其理性地指出了选择 Zig 的代价:
这场讨论最终指向了开发者内心的自我定位:
简单还是控制?这不仅是语言的选择,更是你作为工程师,想要如何与机器对话的选择。
资料链接:https://www.reddit.com/r/Zig/comments/1q38e50/im_really_surprised_by_how_simple_it_is_to/
你的“灵魂选择”
在“简单”与“控制”的天平上,你的心偏向哪一边?如果让你现在开始一个新项目,你会毫不犹豫地选择 Go,还是想尝尝 Zig 的鲜,亦或是死磕 Rust?
欢迎在评论区投出你的一票,并分享你的理由! 让我们看看谁才是开发者心中的“白月光”。
如果这篇文章引发了你的选型思考,别忘了点个【赞】和【在看】,并转发给那个还在纠结学什么语言的朋友!
还在为“复制粘贴喂AI”而烦恼?我的新专栏 《AI原生开发工作流实战》 将带你:
扫描下方二维码,开启你的AI原生开发之旅。

你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?
继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!
我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。
目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

© 2026, bigwhite. 版权所有.
2026-01-16 08:04:27

本文永久链接 – https://tonybai.com/2026/01/16/go-community-the-right-kind-of-abstraction
大家好,我是Tony Bai。
“Go 的哲学强调避免不必要的抽象。”

这句话我们听过无数次。当你试图引入 ORM、泛型 Map/Reduce 、接口或者复杂的设计模式时,往往会收到这样的反馈。这句话本身没有错,但难点在于:到底什么是“不必要”的?
函数是抽象吗?汇编是抽象吗?如果不加定义地“避免抽象”,我们最终只能对着硅片大喊大叫。
在 GopherCon UK 2025 上,John Cinnamond 做了一场与众不同的演讲。他没有展示任何炫酷的并发模式,而是搬出了马丁·海德格尔(Martin Heidegger)和伊曼努尔·康德(Immanuel Kant),试图用哲学的视角,为我们解开关于 Go 抽象的终极困惑。
注:海德格尔与《存在与时间》
马丁·海德格尔(Martin Heidegger)是 20 世纪最重要的哲学家之一。他在 1927 年的巨著《存在与时间》(Being and Time) 中,深入探讨了人(此在)如何与世界互动。John Cinnamond 在演讲中引用的核心概念——“上手状态” (Ready-to-hand) 和 “在手状态” (Present-at-hand),正是海德格尔用来描述我们与工具(如锤子)之间关系的术语。这套理论极好地解释了为什么优秀的工具(或代码抽象)应该是“透明”的,而糟糕的工具则会强行占据我们的注意力。

首先,让我们承认一个事实:编程本身就是建立在无数层抽象之上的。
所以,当我们说“避免不必要的抽象”时,我们真正想表达的其实是——避免“不恰当” (Inappropriate) 的抽象。
那么,如何判断一个抽象是否“恰当”?

在深入探讨“正确”的抽象之前,我们必须先回到最基本的定义。John Cinnamond 在演讲中给出了一个精炼而深刻的定义:
“抽象是一种表示 (Representation),但它是一种刻意移除被表示事物某些细节的表示。”

让我们拆解这个定义:


为什么要刻意移除细节?John 总结了几个核心动机:
但请记住,并非所有抽象都是一样的。John 将它们分为三类:
基于“它是如何工作的” (How it works)
这是为了代码复用而提取的抽象。例如,你发现两处代码都在做“检查用户是否是管理员”的逻辑,于是将其提取为一个函数。这种抽象关注的是内部机制。 (这类抽象通常比较脆弱,一旦实现细节变化,抽象可能就会失效。)
基于“它做了什么” (What it does)
这是 Go 语言中接口(Interface)最典型的用法。例如 io.Reader,我们不关心它是文件还是网络连接,我们只关心它能“读取字节”。这是一种行为抽象。
基于“它是什么” (What it is)
这是基于领域模型的抽象。例如一个 User 结构体,它代表了系统中的一个实体。这种抽象关注的是本质属性。
在现实中,好的抽象往往是这三者的混合体,但在设计时,明确你是在抽象“行为”还是“实现”,对于判断抽象的质量至关重要。

理解了抽象的本质,我们可能会觉得:既然抽象能驾驭复杂性,那是不是越多越好?
且慢。在急于评判一个抽象是否“恰当”之前,我们必须先意识到一个常被技术人员忽略的现实:抽象不仅存在于代码中,更存在于人与人的互动里。 这将我们引向了一个更现实的考量维度。
John 提醒我们,软件开发本质上是一项社会活动 (Social Activity)。
“除非你是为了自己写着玩,否则你的代码总是写给别人看的。团队是一个微型社会,它有自己的习俗、信仰和‘传说’(Lore)。”
引入一个新的抽象,本质上是在向这个微型社会引入一种新的文化或规则。这意味着:

因此,当我们评判一个抽象是否“恰当”时,不能只看代码本身,还必须看它是否“合群”。这正是我们接下来要引入海德格尔哲学的现实基础。
John 引用了海德格尔在《存在与时间》中的一个著名概念:Ready-to-hand (上手状态) 与 Present-at-hand (在手状态)。
这对代码意味着什么?

如果一个抽象让你频繁地从“解决业务问题”中抽离出来去思考“工具本身”,那么它很可能是一个坏的抽象。

注:通过学习和实践,在手状态 (Present-at-hand)的抽象可以转换为 上手状态 (Ready-to-hand)的抽象。
接着,John 又搬出了康德关于真理的分类,引导我们思考抽象的持久性。
这对抽象意味着什么?
当你提取一个抽象时,问问自己:它代表的是代码的“本质真理”,还是仅仅是一个“巧合”?
举个例子:你有一段过滤商品的代码,可以按“价格”过滤,也可以按“库存”过滤。你提取了一个 Filter(Product) bool 的抽象。
如果你提取的抽象仅仅是因为几段代码“长得像”(巧合),而不是因为它们“本质上是一回事”,那么当需求变更时,这个抽象就会崩塌,变成一种负担。
由此可见,好的抽象不是被创造出来的,而是被发现(Recognized)出来的。它们是对代码中某种本质结构的捕捉。
最后,John 给出了一个评估抽象是否“恰当”的五步清单:

Go 社区的“避免不必要的抽象”文化,本质上是对认知负担的防御。我们见过太多为了抽象而抽象的烂代码。但 John 提醒我们,不要因此走向另一个极端——恐惧抽象。

正确且必要的抽象是强大的武器,它能让我们驾驭巨大的复杂性。只要我们能像海德格尔审视锤子那样审视我们的代码,区分“上手”与“在手”,区分“本质”与“巧合”,我们就能在 Go 的简约哲学中,找到属于自己的那条“正确”道路。
资料链接:https://www.youtube.com/watch?v=oP_-eHZSaqc
你的“锤子”顺手吗?
用海德格尔的视角审视代码,确实别有一番风味。在你现在的项目中,有哪些抽象是让你感觉“如臂使指”的(上手状态)?又有哪些抽象经常让你
“出戏”,迫使你不得不去研究它内部的构造(在手状态)?
欢迎在评论区分享你的“哲学思考”! 让我们一起寻找那个最本质的代码真理。
如果这篇文章带给你一次思维的“脑暴”,别忘了点个【赞】和【在看】,并转发给那些喜欢深究技术的伙伴!
还在为“复制粘贴喂AI”而烦恼?我的新专栏 《AI原生开发工作流实战》 将带你:
扫描下方二维码,开启你的AI原生开发之旅。

你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?
继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!
我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。
目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

© 2026, bigwhite. 版权所有.
2026-01-15 08:21:39

本文永久链接 – https://tonybai.com/2026/01/15/where-did-the-memory-go-gopher-unanswered-question
大家好,我是Tony Bai。
“我的服务内存又在缓慢增长了,pprof 显示不出明显的泄漏点……内存到底去哪儿了?”
这句午夜梦回的拷问,或许是许多 Go 开发者心中最深的恐惧。
这一切的根源,可能始于一个你自以为早已掌握的基础问题:“Go 的状态 (state) 存在哪里?” Go 开发者 Abhishek Singh之前断言:“我保证,一大半的 Go 开发者都无法清晰地回答这个问题。”
你的答案是什么?“在 goroutine 里”?“在栈上”?“由 Go runtime 管理”?
如果你的脑中闪过的是这些模糊的念头,那么你可能就找到了“内存失踪案”的“第一案发现场”。这个看似不起眼的认知模糊,正是导致无数生产环境中“内存缓慢泄露”、“goroutine 永不消亡”、“随机延迟飙升”等“灵异事件”的根源。
本文,将为你揭示这个问题的精确答案,并以此为起点,修复你关于 Go 内存管理的“心智模型”,让你从此能够清晰地回答:“内存,到底去哪儿了?”

首先,那个简单而重要的正确答案是:
Go 的状态,就是由 Go runtime 管理的内存,它要么在栈 (stack) 上,要么在堆 (heap) 上。
然而,知道这个答案只是第一步。真正关键的,是摒弃那个导致所有问题的错误直觉,转而建立如下正确的核心心智模型:
Goroutine 不拥有内存,引用 (References) 才拥有。
一个 Goroutine 的退出,并不会释放内存。
当一个 goroutine 结束时,它仅仅是停止了执行。它所创建或引用的任何内存,只要仍然被其他东西持有着引用,就永远不会被垃圾回收器 (GC) 回收。
这些“其他东西”,就是你程序中的“内存锚点”,它们包括:
这,就是几乎所有“Go 内存泄漏”的根本原因。 “内存去哪儿了?”——它被这些看不见的“锚点”,牢牢地拴在了堆上。
Abhishek 将那些导致内存无法被回收的“引用持有者”,形象地称为“内存锚点”。其中,最常见、也最隐蔽的有三种。
创建 goroutine 很廉价,但泄漏它们却极其昂贵。一个典型的“生命周期 Bug”:
// 经典错误:启动一个运行无限循环的 goroutine
go func() {
for {
work() // 假设 work() 会引用一些数据
}
}()
这个 goroutine 永远不会退出。它会永久地持有 work() 函数所引用的任何数据,阻止 GC 回收它们。如果你在每个 HTTP 请求中都启动一个这样的“即发即忘”(fire-and-forget) 的 goroutine,你的服务内存将会线性增长,直至崩溃。
这不是内存泄漏,是你设计了一个“不朽的工作负载”。
Channel 不仅仅是数据的搬运工,它们更是强力的引用持有者。
ch := make(chan *BigStruct)
go func() {
// 这个 goroutine 阻塞在这里,等待向 channel 发送数据
ch <- &BigStruct{...}
}()
// 如果没有其他 goroutine 从 ch 中接收数据...
那么:
这告诉我们:无缓冲或未被消费的 Channel,是缓慢的死亡。 它们会像“锚”一样,将数据和 goroutine 牢牢地钉在内存中。
context 包是 Go 中定义生命周期边界的“标准语言”。然而,一个常见的错误是,启动一个 goroutine 时,向其传递了一个永远不会被取消的 context。
错误模式:
// 传递一个 background context,等于没有传递任何“停止信号”
go doWork(context.Background())
这个 doWork goroutine,一旦启动,就没有任何机制可以通知它停止。如果它内部是一个 for-select 循环,它就会永远运行下去。
正确的模式:
// 从父 context 创建一个可取消的 context
ctx, cancel := context.WithCancel(parentCtx)
// 确保在函数退出时,无论如何都会调用 cancel
defer cancel()
go doWork(ctx)
没有 cancel,就没有清理 (No cancel -> no cleanup)。context 不会“魔法般地”自己取消。

Abhishek 强调,我们习惯于称之为“泄漏”的许多问题,实际上并非 Go 语言的 Bug,而是我们自己设计的“生命周期 Bug”。
pprof (无可争议):这是你的第一、也是最重要的工具。通过 import _ “net/http/pprof” 引入它,并重点关注:
Goroutine Dumps: 通过 curl http://localhost:6060/debug/pprof/goroutine?debug=2 获取所有 goroutine 的详细堆栈信息。如果 goroutine 的数量只增不减,你就找到了泄漏的“犯罪现场”。
灵魂三问 (The Ownership Question):在审查任何一段持有状态的代码时,问自己三个问题:
Go 并没有隐藏内存,它暴露了责任。
GC 无法修复糟糕的所有权设计。
这是本篇最核心、也最深刻的结论。Go 的垃圾回收器,为你解决了“何时 free”的机械问题,但它将一个更高级、也更重要的责任,交还给了你——设计清晰的“所有权”和“生命周期”。
Goroutine 不会自动清理自己,Channel 不会自动排空自己,Context 不会自动取消自己。这些都不是语言的缺陷,而是其设计哲学的体现。
Go 奖励那些能够思考以下问题的工程师:
你不需要成为一名 Go 运行时专家,你只需要开始用“生命周期”的视角,去设计你的并发程序,并偶尔用 pprof 来验证你的设计。
这,就是修复 Go 内存问题“心智模型”的终极之道。
资料链接:https://x.com/0xlelouch_/status/2000485400884785320
你的“捉鬼”经历
内存泄漏就像幽灵,看不见摸不着却真实存在。在你的 Go 开发生涯中,是否也曾遇到过让你抓狂的内存泄漏或 Goroutine 暴涨?最终你是如何定位并解决的?
欢迎在评论区分享你的“捉鬼”故事和独门排查技巧! 让我们一起守护服务的稳定性。
如果这篇文章帮你修复了关于内存的心智模型,别忘了点个【赞】和【在看】,并转发给你的团队,让大家一起避坑!
还在为“复制粘贴喂AI”而烦恼?我的新专栏 《AI原生开发工作流实战》 将带你:
扫描下方二维码,开启你的AI原生开发之旅。

你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?
继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!
我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。
目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

© 2026, bigwhite. 版权所有.