<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tony Bai &#187; Programmer</title>
	<atom:link href="http://tonybai.com/tag/programmer/feed/" rel="self" type="application/rss+xml" />
	<link>https://tonybai.com</link>
	<description>一个程序员的心路历程</description>
	<lastBuildDate>Mon, 27 Apr 2026 22:42:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>看了 100 小时教程，你为什么依然写不好代码？扒开技术人的“成长环”真相</title>
		<link>https://tonybai.com/2026/03/22/stop-tactical-diligence-start-stretch-zone-growth/</link>
		<comments>https://tonybai.com/2026/03/22/stop-tactical-diligence-start-stretch-zone-growth/#comments</comments>
		<pubDate>Sat, 21 Mar 2026 23:51:52 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[ActionQuantity]]></category>
		<category><![CDATA[Agent]]></category>
		<category><![CDATA[AgentCommander]]></category>
		<category><![CDATA[AIAgents]]></category>
		<category><![CDATA[AI智能体]]></category>
		<category><![CDATA[ChangeQuantity]]></category>
		<category><![CDATA[CognitiveAwakening]]></category>
		<category><![CDATA[ComfortZone]]></category>
		<category><![CDATA[DifficultyZone]]></category>
		<category><![CDATA[DynamicRadarChart]]></category>
		<category><![CDATA[EdgeEffortRule]]></category>
		<category><![CDATA[FlowState]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[KnowledgeAccumulation]]></category>
		<category><![CDATA[LearningQuantity]]></category>
		<category><![CDATA[Minimalism]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[SkillDepreciation]]></category>
		<category><![CDATA[SoftwareEngineering]]></category>
		<category><![CDATA[StrategicLaziness]]></category>
		<category><![CDATA[StretchZone]]></category>
		<category><![CDATA[SystemArchitect]]></category>
		<category><![CDATA[TacticalDiligence]]></category>
		<category><![CDATA[TechnicalDebt]]></category>
		<category><![CDATA[ThoughtQuantity]]></category>
		<category><![CDATA[TutorialHell]]></category>
		<category><![CDATA[动态雷达图]]></category>
		<category><![CDATA[困难区]]></category>
		<category><![CDATA[学习量]]></category>
		<category><![CDATA[心流状态]]></category>
		<category><![CDATA[思考量]]></category>
		<category><![CDATA[战术勤奋]]></category>
		<category><![CDATA[战略懒惰]]></category>
		<category><![CDATA[技术债]]></category>
		<category><![CDATA[技能贬值]]></category>
		<category><![CDATA[拉伸区]]></category>
		<category><![CDATA[改变量]]></category>
		<category><![CDATA[教程地狱]]></category>
		<category><![CDATA[智能体]]></category>
		<category><![CDATA[智能体指挥官]]></category>
		<category><![CDATA[极简主义]]></category>
		<category><![CDATA[知识积累]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[系统架构师]]></category>
		<category><![CDATA[舒适区]]></category>
		<category><![CDATA[行动量]]></category>
		<category><![CDATA[认知觉醒]]></category>
		<category><![CDATA[软件工程]]></category>
		<category><![CDATA[边缘努力法则]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=6086</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2026/03/22/stop-tactical-diligence-start-stretch-zone-growth 大家好，我是Tony Bai。 在这个技术大爆炸的时代，我见过了太多极其“勤奋”的程序员： 他们会在各大技术平台上收藏几百篇诸如《Go语言进阶课》、《AI原生开发工作流实战》&#8230; &#8230;的专栏文章，硬盘里塞满了从各种渠道搞来的“AI大模型实战课”视频。他们熬夜看教程、做笔记，甚至在通勤的地铁上都在听技术播客或专栏课程。 但如果你在半年后去问他：“你用 Go 写过什么高并发系统吗？”或者“你开发过什么 AI Agent 吗？” 他大概率会尴尬地挠挠头：“还没，教程太长了还没看完，或者看了感觉太难，平时工作里也用不到……” 为什么看了 100 小时的教程，你依然写不好代码？为什么收藏了无数的技术干货，你的核心竞争力却依然在原地踏步？ 这其实是整个技术圈最普遍、也最隐蔽的陷阱：用“战术上的勤奋”，掩盖了“战略上的懒惰”。 今天，我想跨界借用知名认知作家周岭在《认知觉醒》一书中的核心理论，彻底撕开这层“假性努力”的面纱，带你重新构建一张属于技术人的“动态雷达图”，教你如何真正走出舒适区，在这个 AI 狂飙的时代完成硬核的自我进化。 舒适区与困难区的两极震荡：为什么你总是半途而废？ 在《认知觉醒》中，周岭提出了一个极其精准的人类能力分布模型：“舒适区—拉伸区—困难区”。 这三个同心圆，完美地映射了我们程序员的日常状态： 舒适区（最内层） 在这个区域里，事情对你来说轻车熟路，闭着眼睛都能敲出代码。比如，写一个简单的 CRUD 接口、配置一下 Nginx、复制粘贴一段以前写过的表单验证逻辑。 但问题就在于人类的天性是“避难趋易”的。 长年停留在舒适区，虽然毫无压力，但会让你陷入“无聊而走神”的状态，最终导致技术能力的彻底停滞。在这个区域里，你不是在拥有 10 年经验，你只是把 1 年的经验用了 10 年。 困难区（最外层） 这个区域里的任务，远远超出了你当前的能力边界。比如，你连 Python 都没写熟，就发誓要在一周内从零手搓一个 Transformer 模型；或者你刚学完 Go 基础语法，就想去给 Kubernetes 的底层调度器提核心 PR。 人类的另一个天性是“急于求成，总想一口吃成个胖子”。贸然跨入困难区，你会遇到无数个令人绝望的 Error 报错，巨大的挫败感会瞬间击溃你的自信心，让你产生“我可能不适合干这个”的错觉，最终因畏惧而逃避。 绝大多数技术人的悲剧在于：他们终日在这两极之间做着无效的“钟摆运动”。 平时在公司里做着无聊的 CRUD（舒适区），下班后突然焦虑爆发，立下宏愿要去啃最硬核的底层源码（困难区），被虐得体无完肤后，心灰意冷地退回到继续写 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2026/stop-tactical-diligence-start-stretch-zone-growth-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2026/03/22/stop-tactical-diligence-start-stretch-zone-growth">本文永久链接</a> &#8211; https://tonybai.com/2026/03/22/stop-tactical-diligence-start-stretch-zone-growth</p>
<p>大家好，我是Tony Bai。</p>
<p>在这个技术大爆炸的时代，我见过了太多极其“勤奋”的程序员：</p>
<p>他们会在各大技术平台上收藏几百篇诸如《<a href="http://gk.link/a/12yGY">Go语言进阶课</a>》、《<a href="http://gk.link/a/12EPd">AI原生开发工作流实战</a>》&#8230; &#8230;的专栏文章，硬盘里塞满了从各种渠道搞来的“AI大模型实战课”视频。他们熬夜看教程、做笔记，甚至在通勤的地铁上都在听技术播客或专栏课程。</p>
<p>但如果你在半年后去问他：“你用 Go 写过什么高并发系统吗？”或者“你开发过什么 AI Agent 吗？”</p>
<p>他大概率会尴尬地挠挠头：“还没，教程太长了还没看完，或者看了感觉太难，平时工作里也用不到……”</p>
<p><strong>为什么看了 100 小时的教程，你依然写不好代码？为什么收藏了无数的技术干货，你的核心竞争力却依然在原地踏步？</strong></p>
<p>这其实是整个技术圈最普遍、也最隐蔽的陷阱：<strong>用“战术上的勤奋”，掩盖了“战略上的懒惰”。</strong></p>
<p>今天，我想跨界借用知名认知作家周岭在《<a href="https://book.douban.com/subject/36906244/">认知觉醒</a>》一书中的核心理论，彻底撕开这层“假性努力”的面纱，带你重新构建一张属于技术人的“动态雷达图”，教你如何真正走出舒适区，在这个 AI 狂飙的时代完成硬核的自我进化。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2026/agentic-software-engineering-qr.png" alt="" /></p>
<h2>舒适区与困难区的两极震荡：为什么你总是半途而废？</h2>
<p>在《认知觉醒》中，周岭提出了一个极其精准的人类能力分布模型：<strong>“舒适区—拉伸区—困难区”</strong>。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2026/stop-tactical-diligence-start-stretch-zone-growth-2.png" alt="" /></p>
<p>这三个同心圆，完美地映射了我们程序员的日常状态：</p>
<ol>
<li><strong>舒适区（最内层）</strong> </li>
</ol>
<p>在这个区域里，事情对你来说轻车熟路，闭着眼睛都能敲出代码。比如，写一个简单的 CRUD 接口、配置一下 Nginx、复制粘贴一段以前写过的表单验证逻辑。</p>
<p>但问题就在于人类的天性是“避难趋易”的。</p>
<p>长年停留在舒适区，虽然毫无压力，但会让你陷入“无聊而走神”的状态，最终导致技术能力的彻底停滞。在这个区域里，你不是在拥有 10 年经验，你只是把 1 年的经验用了 10 年。</p>
<ol>
<li><strong>困难区（最外层）</strong></li>
</ol>
<p>这个区域里的任务，远远超出了你当前的能力边界。比如，你连 Python 都没写熟，就发誓要在一周内从零手搓一个 Transformer 模型；或者你刚学完 Go 基础语法，就想去给 Kubernetes 的底层调度器提核心 PR。</p>
<p>人类的另一个天性是“急于求成，总想一口吃成个胖子”。贸然跨入困难区，你会遇到无数个令人绝望的 Error 报错，巨大的挫败感会瞬间击溃你的自信心，让你产生“我可能不适合干这个”的错觉，最终因畏惧而逃避。</p>
<p><strong>绝大多数技术人的悲剧在于：他们终日在这两极之间做着无效的“钟摆运动”。</strong></p>
<p>平时在公司里做着无聊的 CRUD（舒适区），下班后突然焦虑爆发，立下宏愿要去啃最硬核的底层源码（困难区），被虐得体无完肤后，心灰意冷地退回到继续写 CRUD（舒适区）。</p>
<h2>真正的成长密码：寻找你的“拉伸区”（边缘努力法则）</h2>
<p>那么，破局之道在哪里？</p>
<p>答案就藏在舒适区和困难区中间的那个极其狭窄、却又蕴含着巨大能量的环带——<strong>拉伸区（舒适区边缘）</strong>。</p>
<p>在拉伸区里，任务具有一定的挑战性，你无法靠肌肉记忆直接完成，但只要你稍微踮起脚尖，查一查资料，努努力就能触碰到。</p>
<p><strong>这里既有未知的挑战，又有可达成的成就感。只有在这个区域，你才能进入所谓的“心流（Flow）”状态，获得最快的进步。</strong></p>
<p><img src="https://tonybai.com/wp-content/uploads/2026/stop-tactical-diligence-start-stretch-zone-growth-3.png" alt="" /></p>
<p>但这还不够。为了指导我们如何在拉伸区行动，《认知觉醒》中提出了一个更为深刻的“成长微观规律”，它揭示了学习、思考、行动和改变之间的权重关系：</p>
<blockquote>
<p><strong>改变量 > 行动量 > 思考量 > 学习量</strong></p>
</blockquote>
<p>这简直是为程序员量身定制的“照妖镜”！让我们来对照一下：</p>
<ul>
<li><strong>学习量（权重最低）：</strong> 买了一门极客时间的专栏，看完了 10 个视频。这叫输入，你只是把别人的知识存进了大脑的短期记忆里。</li>
<li><strong>思考量：</strong> 看完视频后，你开始琢磨：“哦，原来 Go 的 Channel 底层是一个带锁的环形队列，怪不得会阻塞。”你不仅看了，还理解了。</li>
<li><strong>行动量：</strong> 你打开 IDE，凭着记忆和文档，自己手敲了一段用 Channel 实现的生产者-消费者模型代码，并成功跑通了。</li>
<li><strong>改变量（权重最高）：</strong> 你发现自己手敲的这个并发模型，正好可以用来优化你们公司那个极其缓慢的“每日数据导出”报表脚本。你把它重构并部署上线了，报表导出速度提升了 5 倍！</li>
</ul>
<p><strong>如果你不盯住内层的“改变量”和“行动量”，那么你在表层投入再多的“学习量”也只会事倍功半。</strong></p>
<p>无数人陷入“教程地狱（Tutorial Hell）”的原因，就是他们只停留在了“学习量”的层面，从未产生过“改变量”。</p>
<h2>实战推演：如何利用“拉伸区”构建你的技术雷达图？</h2>
<p>有了宏观的规律支撑，我们该如何将它落地到日常的技术精进中？</p>
<p>优秀的程序员，脑海中都有一张自己的<strong>“动态技术雷达图”</strong>。这张图不是静止的，而是通过在各个技能维度的“拉伸区”不断向外扩张，最终形成一个巨大的“成长环”。</p>
<p>接下来，我将以个人比较熟悉，也是当前较为受欢迎的两个技能领域——<strong>Go 语言高并发开发</strong> 与 <strong>AI Agent 原生开发</strong> 为例，和大家聊聊如何设计自己的拉伸区项目，完成从“学习”到“改变”的闭环。</p>
<h3>案例一：Go 语言开发者的拉伸区跃迁</h3>
<p><strong>现状诊断（舒适区）：</strong></p>
<p>你已经通过《<a href="http://gk.link/a/10AVZ">Go语言第一课</a>》掌握了 Go 的基础语法，能熟练使用 Gin 框架写 HTTP 接口，能用 GORM 对 MySQL 进行增删改查。每天的工作就是对着产品需求堆代码。如果继续这样，三年后你依然是一个高级的“CRUD 工程师”。</p>
<p><strong>急于求成（困难区-千万别去）：</strong></p>
<p>发誓要用 Go 写一个分布式的关系型数据库，或者直接去扒 Go 语言 runtime 包里垃圾回收器（GC）的三色标记法 Go /汇编源码。你会在无尽的底层细节中崩溃。</p>
<p><strong>精心设计的“拉伸区项目”：构建一个高并发的压测小工具</strong></p>
<p>不要去背八股文了，给自己设定一个能触及“改变量”的拉伸区实战项目：用 Go 实现一个类似 ab (Apache Bench) 的高并发压测工具。</p>
<ul>
<li><strong>步骤 1（思考量）：</strong> 为什么原来的单线程脚本发请求那么慢？Go 的 Goroutine 如何做到极轻量级的并发？</li>
<li><strong>步骤 2（行动量 &#8211; 踏入拉伸区）：</strong>
<ul>
<li><strong>拉伸点 1：</strong> 不用任何第三方库，仅用标准库 net/http 发起请求。</li>
<li><strong>拉伸点 2：</strong> 使用 sync.WaitGroup 来控制并发的启动和等待。</li>
<li><strong>拉伸点 3：</strong> 引入 Channel。当并发量达到 10 万时，无脑 go func() 会导致系统资源枯竭。你必须学习使用带缓冲的 Channel 来实现一个<strong>协程池（Worker Pool）</strong>，限制最大并发数。</li>
<li><strong>拉伸点 4：</strong> 引入 sync.Mutex 或 atomic 包，来安全地统计成功请求数、失败数、平均延迟等数据。</li>
</ul>
</li>
<li><strong>步骤 3（改变量 &#8211; 形成闭环）：</strong> 工具写完了。你把它编译成二进制文件扔给测试团队，告诉他们：“以后压测咱们自己的接口，就用我写的这个工具，不需要装乱七八糟的依赖了。”</li>
</ul>
<p>这个项目完美地避开了极其枯燥的底层源码（困难区），又跳出了无脑的框架调用（舒适区）。在这个拉伸区里，你被迫真实地操作了 Goroutine、Channel、锁和原子操作，你的雷达图在“并发编程”这个维度上，成功向外扩张了一大圈。</p>
<h3>案例二：向 AI 原生开发者进化的拉伸区</h3>
<p><strong>现状诊断（舒适区）：</strong></p>
<p>你每天都在用 Copilot 或 Claude Code帮你写代码、润色邮件。你买了几十块钱的 API，用 Python 写了一个脚本，把用户的输入传给 API，然后把结果打印出来。你觉得自己“懂 AI 开发了”。</p>
<p><strong>急于求成（困难区-千万别去）：</strong></p>
<p>去啃 PyTorch 底层逻辑，买几块 4090 显卡，试图自己微调（Fine-tune）一个千亿参数的大模型，或者试图手搓一个全知全能的超级 AGI。</p>
<p><strong>精心设计的“拉伸区项目”：开发一个带“工具调用（Function Calling）”的本地私有知识库助手</strong></p>
<p>从“AI 使用者”到“AI 架构师”的跨越，不在于你能记住多少 Prompt 魔法，而在于你是否懂得如何将 AI 与外部物理世界连接起来。</p>
<ul>
<li><strong>步骤 1（思考量）：</strong> 大模型是没有记忆的，也没有最新数据。如何让大模型能读取我电脑里今天刚生成的日志文件？</li>
<li><strong>步骤 2（行动量 &#8211; 踏入拉伸区）：</strong>
<ul>
<li><strong>拉伸点 1：告别单轮对话。</strong> 学习使用 LLM 的 API 维护一段连续的记忆上下文（Context Management）。</li>
<li><strong>拉伸点 2：攻克 Function Calling（核心拉伸）。</strong> 仔细研读 OpenAI 或 Anthropic 的官方文档，用代码定义一个工具（比如：search_local_file 函数）。这要求你将大模型的自然语言输出，精确地转换为本地函数的结构化参数输入。</li>
<li><strong>拉伸点 3：拥抱最新协议。</strong> 如果你有野心，可以去挑战去年爆火的 MCP（Model Context Protocol）协议，编写一个属于你自己的 MCP Server，让流行的 Agent 工具（如 Cursor 或 Claude Desktop）能够安全地访问你的本地数据库。</li>
</ul>
</li>
<li><strong>步骤 3（改变量 &#8211; 形成闭环）：</strong> 你不再在网页端复制粘贴代码了。你用 Go 或 Python 跑起了一个常驻终端的服务。当你问它“昨天生产环境的报错主要集中在哪里？”时，你的 Agent 自动调用了本地 grep 命令，分析了日志，并给你输出了一份完美的摘要。你的工作效率得到了实质性的改变！</li>
</ul>
<p>这个项目没有要求你去懂深奥的神经网络微积分（困难区），但它逼着你掌握了 AI 原生开发中最核心的“Agent 工具编排”能力。在这个拉伸区里，你从一个“提示词念稿人”，正式蜕变为了一名“AI 指挥官”。</p>
<h2>小结：复利曲线与舒适区边缘的完美交响</h2>
<p>回过头来看看，那些真正牛逼的顶级技术专家，难道他们天生就拥有超凡的智商吗？</p>
<p>绝大多数情况下并不是。</p>
<p>他们的秘密武器，仅仅是<strong>日复一日地在“舒适区的边缘”进行着微小但坚实的努力。</strong></p>
<p>每一次在拉伸区里解决掉一个陌生的 Bug，每一次将一个跑在命令行的脚本优化成一个稳定的后台服务，每一次将你的所学变成真正提高团队效率的工具（改变量），都是在你的技术雷达图上，刻下的一道深深的成长环。</p>
<p>不要再去囤积那些你永远不会看的几十个 G 的视频教程了。</p>
<p>关掉网页，打开你的 IDE。找出你日常开发中最让你感到繁琐的一件小事，稍微踮起脚尖，用你刚学的一点点新知识去干掉它。</p>
<p>去拥抱你的“拉伸区”吧。因为只有在那里，你才能真正体会到作为一名工程师，掌控系统、改变世界的顶级快感。</p>
<hr />
<p><strong>今日互动探讨：</strong></p>
<p>看完这篇文章，你觉得你目前的日常工作有百分之多少是在“舒适区”？如果你要在今年规划一个自己的“拉伸区”硬核项目，你会选择做什么？</p>
<p>欢迎在评论区分享你的反思与计划！</p>
<hr />
<p>还在为“复制粘贴喂AI”而烦恼？我的新专栏 <strong>《<a href="http://gk.link/a/12EPd">AI原生开发工作流实战</a>》</strong> 将带你：</p>
<ul>
<li>告别低效，重塑开发范式</li>
<li>驾驭AI Agent(Claude Code)，实现工作流自动化</li>
<li>从“AI使用者”进化为规范驱动开发的“工作流指挥家”</li>
</ul>
<p>扫描下方二维码，开启你的AI原生开发之旅。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/ai-native-dev-workflow-qr.png" alt="" /></p>
<hr />
<p>你的Go技能，是否也卡在了“熟练”到“精通”的瓶颈期？</p>
<ul>
<li>想写出更地道、更健壮的Go代码，却总在细节上踩坑？</li>
<li>渴望提升软件设计能力，驾驭复杂Go项目却缺乏章法？</li>
<li>想打造生产级的Go服务，却在工程化实践中屡屡受挫？</li>
</ul>
<p>继《<a href="http://gk.link/a/10AVZ">Go语言第一课</a>》后，我的《<a href="http://gk.link/a/12yGY">Go语言进阶课</a>》终于在极客时间与大家见面了！</p>
<p>我的全新极客时间专栏 《<a href="http://gk.link/a/12yGY">Tony Bai·Go语言进阶课</a>》就是为这样的你量身打造！30+讲硬核内容，带你夯实语法认知，提升设计思维，锻造工程实践能力，更有实战项目串讲。</p>
<p>目标只有一个：助你完成从“Go熟练工”到“Go专家”的蜕变！ 现在就加入，让你的Go技能再上一个新台阶！</p>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<hr />
<p><strong>原「Gopher部落」已重装升级为「Go &amp; AI 精进营」知识星球，快来加入星球，开启你的技术跃迁之旅吧！</strong></p>
<p>我们致力于打造一个高品质的 <strong>Go 语言深度学习</strong> 与 <strong>AI 应用探索</strong> 平台。在这里，你将获得：</p>
<ul>
<li><strong>体系化 Go 核心进阶内容:</strong> 深入「Go原理课」、「Go进阶课」、「Go避坑课」等独家深度专栏，夯实你的 Go 内功。</li>
<li><strong>前沿 Go+AI 实战赋能:</strong> 紧跟时代步伐，学习「Go+AI应用实战」、「Agent开发实战课」、「Agentic软件工程课」、「Claude Code开发工作流实战课」、「OpenClaw实战分享」等，掌握 AI 时代新技能。 </li>
<li><strong>星主 Tony Bai 亲自答疑:</strong> 遇到难题？星主第一时间为你深度解析，扫清学习障碍。</li>
<li><strong>高活跃 Gopher 交流圈:</strong> 与众多优秀 Gopher 分享心得、讨论技术，碰撞思想火花。</li>
<li><strong>独家资源与内容首发:</strong> 技术文章、课程更新、精选资源，第一时间触达。</li>
</ul>
<p>衷心希望「Go &amp; AI 精进营」能成为你学习、进步、交流的港湾。让我们在此相聚，享受技术精进的快乐！欢迎你的加入！</p>
<p><img src="http://image.tonybai.com/img/tonybai/gopher-and-ai-tribe-zsxq-small-card.jpg" alt="img{512x368}" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2026, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2026/03/22/stop-tactical-diligence-start-stretch-zone-growth/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Go 的“浮点数陷阱”将被填平：浮点转整数即将在所有平台上行为一致</title>
		<link>https://tonybai.com/2026/01/11/proposal-float-to-int-conversions-should-saturate-on-overflow/</link>
		<comments>https://tonybai.com/2026/01/11/proposal-float-to-int-conversions-should-saturate-on-overflow/#comments</comments>
		<pubDate>Sat, 10 Jan 2026 23:31:45 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[amd64]]></category>
		<category><![CDATA[arm64]]></category>
		<category><![CDATA[Compiler]]></category>
		<category><![CDATA[consistency]]></category>
		<category><![CDATA[Conversion]]></category>
		<category><![CDATA[CrossPlatform]]></category>
		<category><![CDATA[DavidChase]]></category>
		<category><![CDATA[exception]]></category>
		<category><![CDATA[FloatingPoint]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[go1.26]]></category>
		<category><![CDATA[Go1.27]]></category>
		<category><![CDATA[Go1.28]]></category>
		<category><![CDATA[GOEXPERIMENT]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[HardwareDifference]]></category>
		<category><![CDATA[IanLanceTaylor]]></category>
		<category><![CDATA[ImplementationDefined]]></category>
		<category><![CDATA[InstructionSet]]></category>
		<category><![CDATA[Integer]]></category>
		<category><![CDATA[NaN]]></category>
		<category><![CDATA[Overflow]]></category>
		<category><![CDATA[PerfectPortability]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Portability]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[RISCV]]></category>
		<category><![CDATA[SaturatingConversion]]></category>
		<category><![CDATA[一致性]]></category>
		<category><![CDATA[可移植性]]></category>
		<category><![CDATA[完美可移植性]]></category>
		<category><![CDATA[实现定义]]></category>
		<category><![CDATA[异常]]></category>
		<category><![CDATA[性能]]></category>
		<category><![CDATA[指令集]]></category>
		<category><![CDATA[整数]]></category>
		<category><![CDATA[浮点数]]></category>
		<category><![CDATA[溢出]]></category>
		<category><![CDATA[硬件差异]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[编译器]]></category>
		<category><![CDATA[跨平台]]></category>
		<category><![CDATA[转换]]></category>
		<category><![CDATA[饱和转换]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=5703</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2026/01/11/proposal-float-to-int-conversions-should-saturate-on-overflow 大家好，我是Tony Bai。 你是否知道，同一行简单的代码 int64(myFloat)，在 Intel (amd64) 机器上可能返回一个巨大的负数，而在 ARM64 机器上却可能返回最大正整数？ 在 Go 语言中，浮点数到整数的转换溢出行为长期以来一直属于“实现定义”(implementation-dependent) 的灰色地带。这意味着，代码的运行结果竟然取决于你底层的 CPU 架构。这种不确定性，一直是跨平台开发中一个难以察觉的隐形地雷。 2025年末，Go 编译器团队核心成员 David Chase 提交了一份提案（#76264），旨在彻底终结这种混乱。该提案计划在未来的 Go 版本中，强制规定所有平台上的浮点转整数必须是“饱和”的 (saturating)，从而实现真正的全平台行为一致。 痛点：薛定谔的转换结果 在现有的 Go 规范下，如果你尝试将一个超出目标整数范围的浮点数（例如 1e100）转换为 int64，结果是未定义的。 让我们看看这有多疯狂。假设我们有以下代码： var f float64 = 1e100 // 一个巨大的数 var i int64 = int64(f) fmt.Println(i) 这段代码在不同架构下的运行结果截然不同： ARM64, RISC-V: 返回 9223372036854775807 (MAX_INT64)。这是“饱和”行为，即卡在最大值。 AMD64 (x86-64): 返回 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2026/proposal-float-to-int-conversions-should-saturate-on-overflow-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2026/01/11/proposal-float-to-int-conversions-should-saturate-on-overflow">本文永久链接</a> &#8211; https://tonybai.com/2026/01/11/proposal-float-to-int-conversions-should-saturate-on-overflow</p>
<p>大家好，我是Tony Bai。</p>
<p>你是否知道，同一行简单的代码 int64(myFloat)，在 Intel (amd64) 机器上可能返回一个巨大的负数，而在 ARM64 机器上却可能返回最大正整数？</p>
<p>在 Go 语言中，浮点数到整数的转换溢出行为长期以来一直属于“实现定义”(implementation-dependent) 的灰色地带。这意味着，代码的运行结果竟然取决于你底层的 CPU 架构。这种不确定性，一直是跨平台开发中一个难以察觉的隐形地雷。</p>
<p>2025年末，Go 编译器团队核心成员 David Chase 提交了一份提案（<a href="https://github.com/golang/go/issues/76264">#76264</a>），旨在彻底终结这种混乱。该提案计划在未来的 Go 版本中，<strong>强制规定所有平台上的浮点转整数必须是“饱和”的 (saturating)</strong>，从而实现真正的全平台行为一致。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2026/distributed-system-guide-qr.png" alt="img{512x368}" /></p>
<h2>痛点：薛定谔的转换结果</h2>
<p>在现有的 Go 规范下，如果你尝试将一个超出目标整数范围的浮点数（例如 1e100）转换为 int64，结果是未定义的。</p>
<p>让我们看看这有多疯狂。假设我们有以下代码：</p>
<pre><code class="go">var f float64 = 1e100 // 一个巨大的数
var i int64 = int64(f)
fmt.Println(i)
</code></pre>
<p>这段代码在不同架构下的运行结果截然不同：</p>
<ul>
<li><strong>ARM64, RISC-V</strong>: 返回 9223372036854775807 (<strong>MAX_INT64</strong>)。这是“饱和”行为，即卡在最大值。</li>
<li><strong>AMD64 (x86-64)</strong>: 返回 -9223372036854775808 (<strong>MIN_INT64</strong>)。这是一个令人困惑的溢出结果。</li>
<li><strong>WASM</strong>: 行为又不一样&#8230;</li>
</ul>
<p>更糟糕的是 NaN (Not a Number) 的转换：</p>
<pre><code class="go">var j int64 = int64(math.NaN())
fmt.Println(j)
</code></pre>
<ul>
<li><strong>ARM64</strong>: 返回 0。</li>
<li><strong>AMD64</strong>: 返回 <strong>MIN_INT64</strong>。</li>
<li><strong>RISC-V</strong>: 返回 <strong>MAX_INT64</strong>。</li>
</ul>
<p>这种不一致性不仅仅是理论问题，它已经导致了准标准库 x/time/rate 中的真实 Bug (<a href="https://github.com/golang/go/issues/71154">#71154</a>)。当你的代码逻辑依赖于转换结果的正负号来做判断时（例如 if i > 0），这种硬件差异就是致命的。</p>
<h2>解决方案：拥抱“饱和转换”</h2>
<p>David Chase 的提案非常直接：<strong>统一行为，拥抱饱和。</strong></p>
<p>所谓“饱和转换”，是指当浮点数超出目标整数的表示范围时，结果应该被“钳制”在目标类型的最大值或最小值，而不是发生回绕(wraparound)或产生随机值。</p>
<p>具体规则如下：</p>
<ol>
<li><strong>正溢出</strong> -> 返回目标类型的 <strong>最大值</strong> (MaxInt)。</li>
<li><strong>负溢出</strong> -> 返回目标类型的 <strong>最小值</strong> (MinInt)。</li>
<li><strong>NaN</strong> -> 返回 <strong>0</strong> (或归一化为 0)。</li>
</ol>
<p>这一改变将使得 Go 代码在任何 CPU 架构上都表现出完全一致的逻辑，彻底消除了这类可移植性隐患。</p>
<h2>深层权衡：一致性 vs. 性能</h2>
<p>为什么 Go 以前不这么做？核心原因在于<strong>性能成本</strong>。</p>
<p>在 ARM64 和 RISC-V 等现代架构上，硬件指令集（如 FCVT）原生支持饱和转换，因此这样做几乎没有额外开销。</p>
<p>然而，<strong>AMD64 (x86-64) 是个“异类”</strong>。它的 CVTTSD2SQ 指令在溢出时不仅返回一个特殊的“不定值”（通常是 MinInt），还会触发浮点异常。为了在 AMD64 上模拟出“饱和”行为，编译器必须插入额外的检查代码：</p>
<pre><code class="go">// 模拟代码逻辑：AMD64 上的额外开销
result = int64(x)
if result == MIN_INT64 { // 可能溢出了
    if x &gt; 0 {
        result = MAX_INT64 // 正溢出修正
    } else if !(x &lt; 0) {
        result = 0         // NaN 修正
    }
}
</code></pre>
<p>Go 核心团队成员 Ian Lance Taylor 在评论中指出，我们必须权衡：<strong>为了消除这种不一致性，值得让 AMD64 上的转换操作变慢吗？</strong></p>
<p>提案作者 David Chase 的回应是：<strong>值得。</strong> 与 FMA (融合乘加) 指令带来的微小精度差异不同，浮点转整数的差异往往是<strong>正负号级别</strong>的（MaxInt vs MinInt），这直接决定了代码逻辑的走向（循环是否执行、条件是否满足）。这种差异带来的 Bug 极其隐蔽且难以调试，其代价远超那几条指令的性能损耗。</p>
<h2>实施计划：温和的演进</h2>
<p>为了避免生态系统的剧烈震荡，提案建议采用分阶段的落地策略：</p>
<ul>
<li><strong>Go 1.26</strong>: 引入 GOEXPERIMENT 标志，允许开发者尝鲜并测试影响。</li>
<li><strong>Go 1.27</strong>: 将其设为默认的实现行为。</li>
<li><strong>Go 1.28</strong>: 正式修改 Go 语言规范 (Spec)，将其确立为标准。</li>
</ul>
<blockquote>
<p>注：Go 1.26当前已经功能冻结，<a href="https://github.com/golang/go/issues/33892#issuecomment-3721268260">该提案依然处于Go语言规范变更审查委员会的讨论状态中</a>，因此即便逻辑，其实际落地时间表也会顺延。</p>
</blockquote>
<h2>小结：Go 向“完美可移植性”迈出的重要一步</h2>
<p>Dr Chase的这个提案不仅是对一个技术细节的修正，更是 Go 语言设计哲学的一次体现：<strong>在工程实践中，可预测性和可移植性往往优于特定平台上的极致微优化。</strong></p>
<p>如果该提案通过，未来的 Gopher 们将不再需要担心底层的 CPU 是 Intel 还是 ARM，int64(NaN) 永远是 0，int64(Inf) 永远是 MaxInt64。这，才是我们想要的“Write Once, Run Anywhere”。</p>
<blockquote>
<p>注：目前Dr Chase也在努力弥合amd64下的性能差距。</p>
</blockquote>
<p>资料链接：https://github.com/golang/go/issues/76264</p>
<hr />
<p><strong>你的跨平台“血泪史”</strong></p>
<p>跨平台开发中的“未定义行为”往往是最难调试的 Bug。<strong>在你的开发生涯中，是否也遇到过因为 CPU 架构或操作系统差异而导致的诡异问题？你支持为了“一致性”而牺牲一点点 AMD64 上的性能吗？</strong></p>
<p><strong>欢迎在评论区分享你的踩坑经历或对提案的看法！</strong> 让我们一起见证 Go 语言的进化。</p>
<p><strong>如果这篇文章让你对底层原理有了新的认识，别忘了点个【赞】和【在看】，并转发给你的硬核伙伴！</strong></p>
<hr />
<p>还在为“复制粘贴喂AI”而烦恼？我的新专栏 <strong>《<a href="http://gk.link/a/12EPd">AI原生开发工作流实战</a>》</strong> 将带你：</p>
<ul>
<li>告别低效，重塑开发范式</li>
<li>驾驭AI Agent(Claude Code)，实现工作流自动化</li>
<li>从“AI使用者”进化为规范驱动开发的“工作流指挥家”</li>
</ul>
<p>扫描下方二维码，开启你的AI原生开发之旅。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/ai-native-dev-workflow-qr.png" alt="" /></p>
<hr />
<p>你的Go技能，是否也卡在了“熟练”到“精通”的瓶颈期？</p>
<ul>
<li>想写出更地道、更健壮的Go代码，却总在细节上踩坑？</li>
<li>渴望提升软件设计能力，驾驭复杂Go项目却缺乏章法？</li>
<li>想打造生产级的Go服务，却在工程化实践中屡屡受挫？</li>
</ul>
<p>继《<a href="http://gk.link/a/10AVZ">Go语言第一课</a>》后，我的《<a href="http://gk.link/a/12yGY">Go语言进阶课</a>》终于在极客时间与大家见面了！</p>
<p>我的全新极客时间专栏 《<a href="http://gk.link/a/12yGY">Tony Bai·Go语言进阶课</a>》就是为这样的你量身打造！30+讲硬核内容，带你夯实语法认知，提升设计思维，锻造工程实践能力，更有实战项目串讲。</p>
<p>目标只有一个：助你完成从“Go熟练工”到“Go专家”的蜕变！ 现在就加入，让你的Go技能再上一个新台阶！</p>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2026, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2026/01/11/proposal-float-to-int-conversions-should-saturate-on-overflow/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>别演了，真实的程序员根本不修电脑：我们左手AI，右手星辰大海</title>
		<link>https://tonybai.com/2025/12/21/real-programmers-dont-fix-computers-ai-stars-and-seas/</link>
		<comments>https://tonybai.com/2025/12/21/real-programmers-dont-fix-computers-ai-stars-and-seas/#comments</comments>
		<pubDate>Sun, 21 Dec 2025 10:57:06 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[ChatGPT]]></category>
		<category><![CDATA[Claude]]></category>
		<category><![CDATA[deepseek]]></category>
		<category><![CDATA[GarbageCollection]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[GMP]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Optimus]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[raft]]></category>
		<category><![CDATA[RealProgrammers]]></category>
		<category><![CDATA[Slash]]></category>
		<category><![CDATA[SpaceX]]></category>
		<category><![CDATA[Tiktok]]></category>
		<category><![CDATA[Transformer]]></category>
		<category><![CDATA[人情世故]]></category>
		<category><![CDATA[具身智能]]></category>
		<category><![CDATA[刻板印象]]></category>
		<category><![CDATA[垃圾回收]]></category>
		<category><![CDATA[工具人]]></category>
		<category><![CDATA[技术平权]]></category>
		<category><![CDATA[控制算法]]></category>
		<category><![CDATA[斜杠青年]]></category>
		<category><![CDATA[新人类]]></category>
		<category><![CDATA[星舰]]></category>
		<category><![CDATA[星辰大海]]></category>
		<category><![CDATA[神经网络]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[逻辑思维]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=5575</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/12/21/real-programmers-dont-fix-computers-ai-stars-and-seas 大家好，我是Tony Bai。 最近陪家人看几部青春都市剧，实在忍不住想吐槽。 无论题材如何变，编剧笔下的程序员永远是那副德行：戴着黑框眼镜，背着双肩包，唯唯诺诺。而他们的戏份，似乎永远逃不开那一幕—— 男主角或者女神的电脑坏了，喊一声：“喂，那个谁，来修一下。” 然后镜头一转，程序员满头大汗地重启电脑，憨厚一笑。 别演了，真的。 都2025年了，大众对程序员的误解依然停留在“修电脑”和“当备胎”的阶段。 今天，我想撕掉这些标签，聊聊真实的程序员到底在做什么，以及为什么我们这群看似“无趣”的人，实则是未来 30 年人类文明的推手。 “没文化”的工具人？一种中国式的误读 在中国人的传统潜意识里，什么是“有才华”？什么是“有智慧”？ 是引经据典，是出口成章，是懂《周易》懂历史，是酒桌上推杯换盏间的人情练达。我们推崇的是“国学”与“人学”。 而程序员呢？ 我们脑子里装的是 GMP 调度模型，是 Transformer 架构，是 Raft 共识算法。 这些知识的认知门槛极高，掌握难度远超背诵几首唐诗。但在大众眼里，这叫“技能”，不叫“学问”；这叫“工具”，不叫“智慧”。 这就造成了一个巨大的荒诞： 一个能徒手写出操作系统内核的顶级工程师，可能因为在饭局上接不上关于“职场厚黑学”的梗，或者不懂得先敬领导一杯酒，就被贴上“木讷”、“情商低”、“读书读傻了”的标签。 我们不是学不会那些，我们只是不Care。 程序员的思维通过了严苛的逻辑训练，我们习惯了用 O(1) 的复杂度直达本质。对于那些充满了冗余、虚伪和 O(n^2) 复杂度的繁文缛节，我们的大脑会自动执行 Garbage Collection（垃圾回收）。 这种对他人的“降噪”处理，让我们在影视剧里看起来像个“怪胎”，但在代码的世界里，这正是我们构建万物的基石。 格子衫已死：新物种的诞生 如果我们把目光从影视剧移开，看一眼身边真实的 95 后、00 后程序员，你会发现那个“木讷”的标签早已过期。 程序员这个物种，正在经历一次剧烈的“版本迭代”。 去看看现在的互联网大厂，那个传说中的“格子衫军团”正在消失。取而代之的，是滑板少年、是汉服爱好者、是玩死亡重金属的贝斯手。 斜杠青年（Slash）： 你以为他只是个写 Go 语言的后端？下班后，他可能是 B 站拥有十万粉丝的科普 Up 主，可能是独立游戏的制作人，也可能是用 AI 生成艺术画作的数字艺术家。 拒绝被定义： [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/real-programmers-dont-fix-computers-ai-stars-and-seas-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/12/21/real-programmers-dont-fix-computers-ai-stars-and-seas">本文永久链接</a> &#8211; https://tonybai.com/2025/12/21/real-programmers-dont-fix-computers-ai-stars-and-seas</p>
<p>大家好，我是Tony Bai。</p>
<p>最近陪家人看几部青春都市剧，实在忍不住想吐槽。</p>
<p>无论题材如何变，编剧笔下的程序员永远是那副德行：戴着黑框眼镜，背着双肩包，唯唯诺诺。而他们的戏份，似乎永远逃不开那一幕——</p>
<p>男主角或者女神的电脑坏了，喊一声：“喂，那个谁，来修一下。”<br />
然后镜头一转，程序员满头大汗地重启电脑，憨厚一笑。</p>
<p><strong>别演了，真的。</strong></p>
<p>都2025年了，大众对程序员的误解依然停留在“修电脑”和“当备胎”的阶段。</p>
<p>今天，我想撕掉这些标签，聊聊<strong>真实的程序员</strong>到底在做什么，以及为什么我们这群看似“无趣”的人，实则是未来 30 年人类文明的推手。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/api-design-pattern-and-implementation-qr.png" alt="img{512x368}" /></p>
<hr />
<h2>“没文化”的工具人？一种中国式的误读</h2>
<p>在中国人的传统潜意识里，什么是“有才华”？什么是“有智慧”？</p>
<p>是引经据典，是出口成章，是懂《周易》懂历史，是酒桌上推杯换盏间的人情练达。我们推崇的是<strong>“国学”与“人学”</strong>。</p>
<p>而程序员呢？</p>
<p>我们脑子里装的是 <strong>GMP 调度模型</strong>，是 <strong>Transformer 架构</strong>，是 <strong>Raft 共识算法</strong>。</p>
<p>这些知识的<strong>认知门槛</strong>极高，掌握难度远超背诵几首唐诗。但在大众眼里，这叫“技能”，不叫“学问”；这叫“工具”，不叫“智慧”。</p>
<p><strong>这就造成了一个巨大的荒诞：</strong></p>
<p>一个能徒手写出操作系统内核的顶级工程师，可能因为在饭局上接不上关于“职场厚黑学”的梗，或者不懂得先敬领导一杯酒，就被贴上<strong>“木讷”、“情商低”、“读书读傻了”</strong>的标签。</p>
<p>我们不是学不会那些，我们只是<strong>不Care</strong>。</p>
<p>程序员的思维通过了严苛的逻辑训练，我们习惯了用 O(1) 的复杂度直达本质。对于那些充满了冗余、虚伪和 O(n^2) 复杂度的繁文缛节，我们的大脑会自动执行 <strong>Garbage Collection（垃圾回收）</strong>。</p>
<p>这种对他人的“降噪”处理，让我们在影视剧里看起来像个“怪胎”，但在代码的世界里，这正是我们构建万物的基石。</p>
<hr />
<h2>格子衫已死：新物种的诞生</h2>
<p>如果我们把目光从影视剧移开，看一眼身边真实的 95 后、00 后程序员，你会发现那个“木讷”的标签早已过期。</p>
<p><strong>程序员这个物种，正在经历一次剧烈的“版本迭代”。</strong></p>
<p>去看看现在的互联网大厂，那个传说中的“格子衫军团”正在消失。取而代之的，是滑板少年、是汉服爱好者、是玩死亡重金属的贝斯手。</p>
<ul>
<li>
<p><strong>斜杠青年（Slash）：</strong><br />
你以为他只是个写 Go 语言的后端？下班后，他可能是 B 站拥有十万粉丝的科普 Up 主，可能是独立游戏的制作人，也可能是用 AI 生成艺术画作的数字艺术家。</p>
</li>
<li>
<p><strong>拒绝被定义：</strong><br />
如果说上一代程序员的特征是“忍耐”和“沉默”，那么新一代程序员的特征就是<strong>“表达”</strong>和<strong>“重塑”</strong>。他们不屑于酒桌文化，因为他们更崇尚<strong>“技术平权”</strong>和<strong>“透明沟通”</strong>。</p>
</li>
</ul>
<p>这不再是一群只会修电脑的“工具人”，而是一群试图用技术手段去重构生活方式的“新人类”。</p>
<p>他们在 Github 上构建世界，也在小红书和 Tiktok 上分享生活。<strong>他们不是不懂生活，他们是在用代码重新定义什么是“酷”的生活。</strong></p>
<hr />
<h2>左手 AI，右手星辰大海</h2>
<p>影视剧还在忙着刻画我们“修电脑”的窘态，却完全没意识到，这群“配角”，此刻正在现实世界中酝酿着怎样的惊涛骇浪。</p>
<p><strong>我们正站在人类历史最疯狂的转折点上。</strong></p>
<p>当你嘲笑程序员不懂“风花雪月”时，他们正在做上帝的工作：</p>
<ul>
<li>
<p><strong>左手，赋予机器“灵魂”与“肉体”：</strong><br />
那些让你惊叹的 ChatGPT、Claude、DeepSeek，背后是程序员用代码搭建的神经网络。宇树G1/H1，特斯拉的 Optimus等人形机器人，正在走进现实。是程序员将逻辑注入钢铁躯体，让机器人学会行走、抓取，甚至学会思考。<strong>具身智能</strong>的爆发，将彻底重塑物理世界。</p>
</li>
<li>
<p><strong>右手，征服星辰大海：</strong><br />
SpaceX 的“筷子”夹住星舰的那一刻，全球沸腾。那毫秒级的姿态调整，不是靠吟诗作对实现的，而是靠几十万行严密的<strong>控制算法</strong>。</p>
</li>
</ul>
<p><strong>谁才是这个时代的“男一号”？</strong></p>
<p>是那些在剧里谈情说爱的主角吗？不。</p>
<p>是那些在屏幕后，用 Go 语言重构微服务，用 Python 训练大模型，用 C++ 控制火箭姿态的所谓“码农”。</p>
<p><strong>流行文化在消费我们，而我们在重塑流行文化赖以生存的世界。</strong></p>
<p>国学典籍是<strong>面向过去</strong>的接口，它教我们如何维系一个稳定的人情社会；</p>
<p>编程语言是<strong>面向未来</strong>的接口，它教我们如何与硅基生命对话，如何在此刻定义未来 30 年的规则。</p>
<hr />
<h2>小结：致敬时代的推手</h2>
<p>也许在未来的很长一段时间里，影视剧里的程序员依然会是那个戴着眼镜、不懂风情的“路人甲”。</p>
<p>没关系。让我们接受这种“误读”。</p>
<p>因为这种“忽视”，恰恰是一种保护色。它让我们这群人能远离嘈杂的名利场和复杂的人际关系，心无旁骛地坐在屏幕前。</p>
<p><strong>我们不需要修电脑，我们在修补这个世界的 Bug；</strong></p>
<p><strong>我们不需要当偶像剧的主角，我们在编写人类文明的下一个版本。</strong></p>
<p>致敬每一位“不善言辞”，但正在改变世界的程序员。</p>
<hr />
<p><strong>作为程序员，你曾在哪一刻因为“不懂人情世故”或“不关注大众话题”而被误解过？而在那一刻，你脑子里其实正在思考什么硬核的技术问题？</strong></p>
<p>欢迎在评论区，分享你的“社死”与“高光”时刻。</p>
<hr />
<p><strong>未来30年，是属于工程师的黄金时代。</strong></p>
<p>别让你的技能停留在“修电脑”的阶段。想要掌握 <strong>Go 语言在云原生、AI 工程化</strong> 中的核心能力，紧跟 <strong>具身智能</strong> 的浪潮？</p>
<p>加入我的 <strong>「Go &amp; AI 精进营」</strong>。在这里，我们不聊厚黑学，只聊如何拿到通往未来的船票。</p>
<p><strong>[此处放置知识星球二维码]</strong></p>
<hr />
<p>还在为“复制粘贴喂AI”而烦恼？我的新专栏 <strong>《<a href="http://gk.link/a/12EPd">AI原生开发工作流实战</a>》</strong> 将带你：</p>
<ul>
<li>告别低效，重塑开发范式</li>
<li>驾驭AI Agent(Claude Code)，实现工作流自动化</li>
<li>从“AI使用者”进化为规范驱动开发的“工作流指挥家”</li>
</ul>
<p>扫描下方二维码，开启你的AI原生开发之旅。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/ai-native-dev-workflow-qr.png" alt="" /></p>
<hr />
<p>你的Go技能，是否也卡在了“熟练”到“精通”的瓶颈期？</p>
<ul>
<li>想写出更地道、更健壮的Go代码，却总在细节上踩坑？</li>
<li>渴望提升软件设计能力，驾驭复杂Go项目却缺乏章法？</li>
<li>想打造生产级的Go服务，却在工程化实践中屡屡受挫？</li>
</ul>
<p>继《<a href="http://gk.link/a/10AVZ">Go语言第一课</a>》后，我的《<a href="http://gk.link/a/12yGY">Go语言进阶课</a>》终于在极客时间与大家见面了！</p>
<p>我的全新极客时间专栏 《<a href="http://gk.link/a/12yGY">Tony Bai·Go语言进阶课</a>》就是为这样的你量身打造！30+讲硬核内容，带你夯实语法认知，提升设计思维，锻造工程实践能力，更有实战项目串讲。</p>
<p>目标只有一个：助你完成从“Go熟练工”到“Go专家”的蜕变！ 现在就加入，让你的Go技能再上一个新台阶！</p>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/12/21/real-programmers-dont-fix-computers-ai-stars-and-seas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>给了机关枪，你却非要耍大刀：2025 年末，程序员 All in AI 的生存启示录</title>
		<link>https://tonybai.com/2025/12/09/programmer-all-in-ai-survival-revelation-in-2025/</link>
		<comments>https://tonybai.com/2025/12/09/programmer-all-in-ai-survival-revelation-in-2025/#comments</comments>
		<pubDate>Tue, 09 Dec 2025 00:17:51 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[2025年末]]></category>
		<category><![CDATA[AgenticTools]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[AI原生工作流]]></category>
		<category><![CDATA[AllinAI]]></category>
		<category><![CDATA[ChainofThought]]></category>
		<category><![CDATA[ChatGPT]]></category>
		<category><![CDATA[ClaudeCode]]></category>
		<category><![CDATA[ContextInjection]]></category>
		<category><![CDATA[Copilot]]></category>
		<category><![CDATA[Cursor]]></category>
		<category><![CDATA[EditorinChief]]></category>
		<category><![CDATA[Hallucination]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[SDD]]></category>
		<category><![CDATA[SpecDriven]]></category>
		<category><![CDATA[syntax]]></category>
		<category><![CDATA[Windsurf]]></category>
		<category><![CDATA[价值判断]]></category>
		<category><![CDATA[伪精英心态]]></category>
		<category><![CDATA[外骨骼]]></category>
		<category><![CDATA[大刀]]></category>
		<category><![CDATA[思维躺平]]></category>
		<category><![CDATA[总编辑]]></category>
		<category><![CDATA[技术洁癖]]></category>
		<category><![CDATA[智能体]]></category>
		<category><![CDATA[机关枪]]></category>
		<category><![CDATA[概率预测]]></category>
		<category><![CDATA[生存启示录]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[规范驱动开发]]></category>
		<category><![CDATA[认知重构]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=5502</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/12/09/programmer-all-in-ai-survival-revelation-in-2025 大家好，我是Tony Bai。 最近逛 Twitter 和技术论坛，我发现了一个非常有意思，甚至有些魔幻的现象。 尽管我们已经站在了 2025 年末，距离 ChatGPT 震撼发布已经过去了整整三年，AI 能力早已从“玩具”进化成了“重型武器”。但在评论区里，依然充斥着大量这样的声音： “真程序员谁用 AI 啊，那都是给脚本小子用的。” “用 AI 生成代码没有灵魂，我还是习惯自己掌控每一个字符。” &#8230; &#8230; 看着这些言论，再联想到身边团队和朋友圈中的一些类似的现象，我忍不住在我的知识星球中发了一句感慨： “给了你机关枪，你却非得用大刀。这不仅是不合时宜，简直是暴殄天物” 这三年，AI 不再是那个只会写打油诗的聊天机器人，它是基建，是水电，是程序员的第二大脑。 在这个时间节点，命题早已改变：不再是“要不要用 AI”，而是“你为什么还在用大刀砍柴？” 但在真正 All in AI 之前，我们必须先看清现实中普遍存在的“四大怪象”，并一一打破它们。 现实中的“四大怪象” 如果你仔细观察身边的技术团队，朋友圈或者审视一下自己，可能就会发现我们都在不自觉地陷入以下误区： 怪象一：技术洁癖引发的“伪精英心态” 很多人认为依赖工具是能力退化的表现。他们以“纯手工打造”为荣，认为只有自己敲出来的代码/文字才叫硬核，用 AI 就像是“作弊”。 怪象二：工具依赖导致的“思维躺平” 另一极端是，有了 AI 就不思考了。遇到问题直接扔给 AI，AI 给什么就用什么，不再去探究底层的原理，甚至觉得“反正 AI 会，我不用学了”。 怪象三：盲目信任带来的“埋雷行为” 把 AI 当作真理的化身。直接 Copy &#38; Paste AI [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/programmer-all-in-ai-survival-revelation-in-2025-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/12/09/programmer-all-in-ai-survival-revelation-in-2025">本文永久链接</a> &#8211; https://tonybai.com/2025/12/09/programmer-all-in-ai-survival-revelation-in-2025</p>
<p>大家好，我是Tony Bai。</p>
<p>最近逛 Twitter 和技术论坛，我发现了一个非常有意思，甚至有些魔幻的现象。</p>
<p>尽管我们已经站在了 <strong>2025 年末</strong>，距离 ChatGPT 震撼发布已经过去了整整三年，AI 能力早已从“玩具”进化成了“重型武器”。但在评论区里，依然充斥着大量这样的声音：</p>
<ul>
<li>“真程序员谁用 AI 啊，那都是给脚本小子用的。”</li>
<li>“用 AI 生成代码没有灵魂，我还是习惯自己掌控每一个字符。”</li>
<li>&#8230; &#8230;</li>
</ul>
<p>看着这些言论，再联想到身边团队和朋友圈中的一些类似的现象，我忍不住在我的知识星球中发了一句感慨：</p>
<p><strong>“给了你机关枪，你却非得用大刀。这不仅是不合时宜，简直是暴殄天物”</strong></p>
<p>这三年，AI 不再是那个只会写打油诗的聊天机器人，它是基建，是水电，是程序员的第二大脑。</p>
<p>在这个时间节点，命题早已改变：不再是“要不要用 AI”，而是<strong>“你为什么还在用大刀砍柴？”</strong></p>
<p>但在真正 All in AI 之前，我们必须先看清现实中普遍存在的<strong>“四大怪象”</strong>，并一一打破它们。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/programmer-all-in-ai-survival-revelation-in-2025-2.png" alt="" /></p>
<hr />
<h2>现实中的“四大怪象”</h2>
<p>如果你仔细观察身边的技术团队，朋友圈或者审视一下自己，可能就会发现我们都在不自觉地陷入以下误区：</p>
<p><strong>怪象一：技术洁癖引发的“伪精英心态”</strong></p>
<p>很多人认为依赖工具是能力退化的表现。他们以“纯手工打造”为荣，认为只有自己敲出来的代码/文字才叫硬核，用 AI 就像是“作弊”。</p>
<p><strong>怪象二：工具依赖导致的“思维躺平”</strong></p>
<p>另一极端是，有了 AI 就不思考了。遇到问题直接扔给 AI，AI 给什么就用什么，不再去探究底层的原理，甚至觉得“反正 AI 会，我不用学了”。</p>
<p><strong>怪象三：盲目信任带来的“埋雷行为”</strong></p>
<p>把 AI 当作真理的化身。直接 Copy &amp; Paste AI 生成的代码上线，不看逻辑，不测边界，结果把 AI 的幻觉（Hallucination）直接变成了线上的 Bug。</p>
<p><strong>怪象四：浅尝辄止的“低效勤奋”</strong></p>
<p>虽然也在用 AI，但只停留在“帮我写个正则”、“解释这段代码”的浅层阶段。手里拿着加特林机关枪，却只把它当烧火棍用。</p>
<hr />
<h2>All in AI 之前的“四重认知突围”</h2>
<p>针对上述怪象，如果想在 2025 年以及未来几年生存并晋级，我们需要进行一次彻底的认知重构。</p>
<h3>认知 1：拒绝羞耻感 —— 它是“外骨骼”，不是“轮椅”</h3>
<p><em>(对标怪象一)</em></p>
<p>越是基本功扎实的老兵，越容易有“技术羞耻感”。请立刻抛弃这种旧思维。</p>
<p>在 2025 年，<strong>能力定义的公式变了</strong>。</p>
<ul>
<li>旧能力 = 记忆力 + 手速 + 经验</li>
<li>新能力 = <strong>(经验 + 洞察) × AI 算力</strong></li>
</ul>
<p>使用 AI 不是因为你“能力不行”需要轮椅，而是为了<strong>放大</strong>你的能力。它让你从繁琐的语法/文书细节（Syntax）中解脱出来，让你的架构设计能力得以十倍级释放。<strong>善用“机关枪”是特种兵的素养，不是逃兵的借口。</strong></p>
<h3>认知 2：拒绝躺平 —— 是“升维”，不是“减负”</h3>
<p><em>(对标怪象二)</em></p>
<p>以为用了 AI 就可以不学习了？大错特错。</p>
<p><strong>AI 时代的学习逻辑发生了倒置：</strong> AI 负责“已知知识的检索与生成”，你负责“未知领域的洞察与判断”。</p>
<p>当 AI 帮你搞定了 80% 的“实现细节（How）”，你必须把节省下来的精力，投入到那 20% 更核心的“价值判断（Why &amp; What）”中。</p>
<p>你不仅不能停止学习，反而要学得更深、更广——否则你甚至不知道该如何向 AI 提问，更不知道如何判断它给出的方案是平庸还是卓越。</p>
<h3>认知 3：坚守底线 —— 做“机长”，不做“乘客”</h3>
<p><em>(对标怪象三)</em></p>
<p>AI 的第一性原理（概率预测）决定了它永远存在“一本正经胡说八道”的可能。</p>
<p><strong>对 AI 输出的成果物进行严苛的审核 (Review)，是任何成果物发布前的必经路径。</strong></p>
<p>你需要从“Writer（撰稿人）”转型为<strong>“Editor-in-Chief（总编辑）”</strong>。</p>
<p>你是机长，AI 是副驾驶。它负责操作仪表盘，但<strong>你负责决定航向，并对每一次降落的安全性负责。</strong> 没有审核的 AI 代码/文档，就是一颗定时炸弹。这意味着你不能只看代码跑通了没有，还要像审查实习生代码一样，去盘问它的逻辑漏洞和边缘情况。</p>
<h3>认知 4：直面竞争 —— 比的是“枪法”，不是“有枪”</h3>
<p><em>(对标怪象四)</em></p>
<p>三年过去，AI 已经祛魅。现在人人手里都有一把“机关枪”（Cursor, Claude Code, Copilot 等）。</p>
<p>竞争的维度变了：<strong>不再是谁有枪（因为大家都有），而是谁的枪法更准。</strong></p>
<ul>
<li><strong>初级枪法：</strong> 单轮对话，只会问简单问题。</li>
<li><strong>高级枪法：</strong> 懂得 Context Injection（上下文注入）、Chain of Thought（思维链）、Spec-Driven（规范驱动开发工作流）。</li>
</ul>
<p><strong>“都用 AI”只是入场券。</strong> 真正的比拼，在于谁用得更深、更精，谁能用这把枪打出“百步穿杨”的效果。</p>
<hr />
<h2>小结：是时候All in AI了！</h2>
<p>技术历史的车轮滚滚向前，残酷性从未改变。</p>
<p>每一次技术范式的转移，都会留下一批抱残守缺的“大刀队”。他们不是不努力，他们甚至比谁都辛苦，每天挥舞大刀砍得汗流浃背，但在“机关枪”的扫射下，这种努力显得苍白无力。</p>
<p><strong>2025 年末，放下你的大刀吧。</strong></p>
<p>去学习怎么校准瞄准镜，怎么控制后坐力，怎么设计交叉火力网。这不丢人。这才是对技术、对自己职业生涯最大的尊重。</p>
<hr />
<p><strong>互动话题</strong></p>
<p>在使用 AI 编程的过程中，你遇到过最让你“细思极恐”的时刻是什么？或者最让你感到“真香”的瞬间是什么？欢迎在留言区分享你的故事。</p>
<hr />
<p><strong>如何练就“百步穿杨”的枪法？</strong></p>
<p>文章里我们说了，“都用 AI”只是入场券，真正的决胜点在于<strong>谁用得更深、更精，谁拥有一套高维度的“AI 原生工作流”</strong>。</p>
<p>如果你已经决定放下“大刀”，拿起“机关枪”，但面对市面上眼花缭乱的工具（Claude Code, Cursor, Windsurf）和碎片化的技巧，感到无从下手；</p>
<p>或者你虽然用了 AI，但发现自己依然陷入在“改 Bug -> AI 生成新 Bug”的低效死循环中；</p>
<p>那么，欢迎加入我的极客时间专栏<strong>《AI 原生开发工作流实战》</strong>。</p>
<p>在这里，我们将深入实战：</p>
<ul>
<li><strong>重构开发范式：</strong> 彻底告别“聊天式编程”，掌握 <strong>SDD (规范驱动开发)</strong> 的核心心法，学会用 Spec 文档精准指挥 AI。</li>
<li><strong>驾驭 Agentic 系统：</strong> 深入剖析 Claude Code 等 <strong>Agentic Tools</strong> 的底层逻辑，把它们变成你忠实的“外包团队”。</li>
<li><strong>构建私有/团队工作流：</strong> 手把手教你搭建一套<strong>“人脑定义目标 + AI 并发执行”</strong>的高效流水线。</li>
</ul>
<p><strong>别让手里的机关枪生锈。</strong> 点击下方卡片，我们一起在实战中进化。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/ai-native-dev-workflow-qr.png" alt="" /></p>
<hr />
<p>你的Go技能，是否也卡在了“熟练”到“精通”的瓶颈期？</p>
<ul>
<li>想写出更地道、更健壮的Go代码，却总在细节上踩坑？</li>
<li>渴望提升软件设计能力，驾驭复杂Go项目却缺乏章法？</li>
<li>想打造生产级的Go服务，却在工程化实践中屡屡受挫？</li>
</ul>
<p>继《<a href="http://gk.link/a/10AVZ">Go语言第一课</a>》后，我的《<a href="http://gk.link/a/12yGY">Go语言进阶课</a>》终于在极客时间与大家见面了！</p>
<p>我的全新极客时间专栏 《<a href="http://gk.link/a/12yGY">Tony Bai·Go语言进阶课</a>》就是为这样的你量身打造！30+讲硬核内容，带你夯实语法认知，提升设计思维，锻造工程实践能力，更有实战项目串讲。</p>
<p>目标只有一个：助你完成从“Go熟练工”到“Go专家”的蜕变！ 现在就加入，让你的Go技能再上一个新台阶！</p>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/12/09/programmer-all-in-ai-survival-revelation-in-2025/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>从《凡人修仙传》到《三体》：顶尖程序员的“降维打击”与“法则”之力</title>
		<link>https://tonybai.com/2025/10/24/from-fanren-to-three-body-top-programmers-power/</link>
		<comments>https://tonybai.com/2025/10/24/from-fanren-to-three-body-top-programmers-power/#comments</comments>
		<pubDate>Fri, 24 Oct 2025 14:28:56 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[Biology]]></category>
		<category><![CDATA[BlindFollowing]]></category>
		<category><![CDATA[Bottleneck]]></category>
		<category><![CDATA[BugExclusion]]></category>
		<category><![CDATA[Bug排除]]></category>
		<category><![CDATA[BuildYourOwnWheel]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[CacheLine]]></category>
		<category><![CDATA[CartesianProduct]]></category>
		<category><![CDATA[CausalLaw]]></category>
		<category><![CDATA[Classics]]></category>
		<category><![CDATA[cloudnative]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[CompilerPrinciple]]></category>
		<category><![CDATA[Complexity]]></category>
		<category><![CDATA[ComputerArchitecture]]></category>
		<category><![CDATA[ComputerNetwork]]></category>
		<category><![CDATA[ComputerScienceFundamentalLaws]]></category>
		<category><![CDATA[ComputingPower]]></category>
		<category><![CDATA[ConstructionLaw]]></category>
		<category><![CDATA[controller]]></category>
		<category><![CDATA[CorePrinciple]]></category>
		<category><![CDATA[CosmicLaws]]></category>
		<category><![CDATA[Creation]]></category>
		<category><![CDATA[CrossDisciplinaryLearning]]></category>
		<category><![CDATA[CultivatingSkills]]></category>
		<category><![CDATA[CultivationPath]]></category>
		<category><![CDATA[CultivationRealm]]></category>
		<category><![CDATA[Curiosity]]></category>
		<category><![CDATA[Cybernetics]]></category>
		<category><![CDATA[DataStructure]]></category>
		<category><![CDATA[DefineFuture]]></category>
		<category><![CDATA[Desire]]></category>
		<category><![CDATA[DifficultToMigrate]]></category>
		<category><![CDATA[DimensionalityReductionAttack]]></category>
		<category><![CDATA[DistributedTheory]]></category>
		<category><![CDATA[Economics]]></category>
		<category><![CDATA[engineer]]></category>
		<category><![CDATA[FanrenXiuxianzhuan]]></category>
		<category><![CDATA[FirstPrinciples]]></category>
		<category><![CDATA[Fog]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[GCStoppage]]></category>
		<category><![CDATA[GC停顿]]></category>
		<category><![CDATA[GeekTime]]></category>
		<category><![CDATA[GoLanguage]]></category>
		<category><![CDATA[GoLanguageAdvancedCourse]]></category>
		<category><![CDATA[GoLanguagePrimer]]></category>
		<category><![CDATA[GoSkill]]></category>
		<category><![CDATA[Go技能]]></category>
		<category><![CDATA[Go语言]]></category>
		<category><![CDATA[Go语言第一课]]></category>
		<category><![CDATA[Go语言进阶课]]></category>
		<category><![CDATA[Grandmaster]]></category>
		<category><![CDATA[HashTable]]></category>
		<category><![CDATA[HeavenAndEarthLaws]]></category>
		<category><![CDATA[HighAvailability]]></category>
		<category><![CDATA[HighConcurrency]]></category>
		<category><![CDATA[HighLevelLanguage]]></category>
		<category><![CDATA[Implementation]]></category>
		<category><![CDATA[Insight]]></category>
		<category><![CDATA[Intelligence]]></category>
		<category><![CDATA[KnowWhatButNotWhy]]></category>
		<category><![CDATA[latency]]></category>
		<category><![CDATA[LessonsFromOthers]]></category>
		<category><![CDATA[Light]]></category>
		<category><![CDATA[LoadBalancing]]></category>
		<category><![CDATA[LowCeiling]]></category>
		<category><![CDATA[MachineInstruction]]></category>
		<category><![CDATA[MagicSpell]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[MemoryManagement]]></category>
		<category><![CDATA[Metaphysics]]></category>
		<category><![CDATA[MicroserviceArchitecture]]></category>
		<category><![CDATA[MonolithicApplication]]></category>
		<category><![CDATA[NestedLoop]]></category>
		<category><![CDATA[OperationsCost]]></category>
		<category><![CDATA[Origin]]></category>
		<category><![CDATA[PerformanceBottleneck]]></category>
		<category><![CDATA[PerformanceOptimization]]></category>
		<category><![CDATA[PersonalVerification]]></category>
		<category><![CDATA[Physics]]></category>
		<category><![CDATA[pipeline]]></category>
		<category><![CDATA[PointerJump]]></category>
		<category><![CDATA[PowerOfLaw]]></category>
		<category><![CDATA[Practice]]></category>
		<category><![CDATA[Principle]]></category>
		<category><![CDATA[PrincipleUnderstander]]></category>
		<category><![CDATA[ProductionEnvironment]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[RaceCondition]]></category>
		<category><![CDATA[ReadSourceCode]]></category>
		<category><![CDATA[RebuildFoundation]]></category>
		<category><![CDATA[RedundantBackup]]></category>
		<category><![CDATA[RefiningMaster]]></category>
		<category><![CDATA[RestartMethod]]></category>
		<category><![CDATA[SanTi]]></category>
		<category><![CDATA[Sect]]></category>
		<category><![CDATA[ServerUpgrade]]></category>
		<category><![CDATA[SettleDownAndLive]]></category>
		<category><![CDATA[SharedVariable]]></category>
		<category><![CDATA[Skill]]></category>
		<category><![CDATA[SkillCultivator]]></category>
		<category><![CDATA[SkilledWorker]]></category>
		<category><![CDATA[SpaceLaw]]></category>
		<category><![CDATA[SpecificMethods]]></category>
		<category><![CDATA[SpiralAscent]]></category>
		<category><![CDATA[StabilizeFoundation]]></category>
		<category><![CDATA[SupremeLaw]]></category>
		<category><![CDATA[SystemDesign]]></category>
		<category><![CDATA[TechnologyCycle]]></category>
		<category><![CDATA[TechnologySelection]]></category>
		<category><![CDATA[ThreadSafety]]></category>
		<category><![CDATA[TimeLaw]]></category>
		<category><![CDATA[tool]]></category>
		<category><![CDATA[TopProgrammer]]></category>
		<category><![CDATA[TrialAndError]]></category>
		<category><![CDATA[TwoDimensionalFoil]]></category>
		<category><![CDATA[UnderlyingPrinciples]]></category>
		<category><![CDATA[UnderstandingPrinciples]]></category>
		<category><![CDATA[UnderstandMagicOrigin]]></category>
		<category><![CDATA[UniversalTruthsAreConnected]]></category>
		<category><![CDATA[Unreliability]]></category>
		<category><![CDATA[UnstableFoundation]]></category>
		<category><![CDATA[三体]]></category>
		<category><![CDATA[不可靠性]]></category>
		<category><![CDATA[二向箔]]></category>
		<category><![CDATA[云原生]]></category>
		<category><![CDATA[亲身证道]]></category>
		<category><![CDATA[他山之石]]></category>
		<category><![CDATA[代码]]></category>
		<category><![CDATA[修仙境界]]></category>
		<category><![CDATA[修术]]></category>
		<category><![CDATA[修术者]]></category>
		<category><![CDATA[修行路线]]></category>
		<category><![CDATA[光芒]]></category>
		<category><![CDATA[共享变量]]></category>
		<category><![CDATA[具体功法]]></category>
		<category><![CDATA[内存管理]]></category>
		<category><![CDATA[冗余备份]]></category>
		<category><![CDATA[凡人修仙传]]></category>
		<category><![CDATA[分布式理论]]></category>
		<category><![CDATA[创造]]></category>
		<category><![CDATA[动手造轮子]]></category>
		<category><![CDATA[升级服务器]]></category>
		<category><![CDATA[单体应用]]></category>
		<category><![CDATA[哈希表]]></category>
		<category><![CDATA[因果法则]]></category>
		<category><![CDATA[复杂度]]></category>
		<category><![CDATA[大道相通]]></category>
		<category><![CDATA[天地法则]]></category>
		<category><![CDATA[天花板低]]></category>
		<category><![CDATA[好奇]]></category>
		<category><![CDATA[宇宙规律]]></category>
		<category><![CDATA[安身立命]]></category>
		<category><![CDATA[宗师]]></category>
		<category><![CDATA[宗门]]></category>
		<category><![CDATA[定义未来]]></category>
		<category><![CDATA[实现]]></category>
		<category><![CDATA[实践]]></category>
		<category><![CDATA[嵌套循环]]></category>
		<category><![CDATA[工具]]></category>
		<category><![CDATA[工程师]]></category>
		<category><![CDATA[底层原理]]></category>
		<category><![CDATA[延迟]]></category>
		<category><![CDATA[微服务架构]]></category>
		<category><![CDATA[心法总纲]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[性能瓶颈]]></category>
		<category><![CDATA[悟道]]></category>
		<category><![CDATA[悟道者]]></category>
		<category><![CDATA[技术周期]]></category>
		<category><![CDATA[技术选型]]></category>
		<category><![CDATA[指针跳转]]></category>
		<category><![CDATA[掌控者]]></category>
		<category><![CDATA[控制论]]></category>
		<category><![CDATA[数学]]></category>
		<category><![CDATA[数据结构]]></category>
		<category><![CDATA[时间法则]]></category>
		<category><![CDATA[智力]]></category>
		<category><![CDATA[本源]]></category>
		<category><![CDATA[术]]></category>
		<category><![CDATA[机器指令]]></category>
		<category><![CDATA[极客时间]]></category>
		<category><![CDATA[构造法则]]></category>
		<category><![CDATA[根基不稳]]></category>
		<category><![CDATA[框架]]></category>
		<category><![CDATA[法则之力]]></category>
		<category><![CDATA[法术]]></category>
		<category><![CDATA[洞察力]]></category>
		<category><![CDATA[洞悉法术本源]]></category>
		<category><![CDATA[流水线]]></category>
		<category><![CDATA[渴望]]></category>
		<category><![CDATA[炼器大师]]></category>
		<category><![CDATA[熟练工]]></category>
		<category><![CDATA[物理学]]></category>
		<category><![CDATA[玄学]]></category>
		<category><![CDATA[瓶颈]]></category>
		<category><![CDATA[生产环境]]></category>
		<category><![CDATA[生物学]]></category>
		<category><![CDATA[盲目跟风]]></category>
		<category><![CDATA[知其然不知其所以然]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[稳固道基]]></category>
		<category><![CDATA[空间法则]]></category>
		<category><![CDATA[竞态条件]]></category>
		<category><![CDATA[笛卡尔积]]></category>
		<category><![CDATA[第一性原理]]></category>
		<category><![CDATA[算力]]></category>
		<category><![CDATA[算法]]></category>
		<category><![CDATA[系统设计]]></category>
		<category><![CDATA[线程安全]]></category>
		<category><![CDATA[经典]]></category>
		<category><![CDATA[经济学]]></category>
		<category><![CDATA[缓存]]></category>
		<category><![CDATA[缓存行]]></category>
		<category><![CDATA[编译原理]]></category>
		<category><![CDATA[至尊法则]]></category>
		<category><![CDATA[螺旋上升]]></category>
		<category><![CDATA[计算机体系结构]]></category>
		<category><![CDATA[计算机科学基础法则]]></category>
		<category><![CDATA[计算机网络]]></category>
		<category><![CDATA[试错法]]></category>
		<category><![CDATA[负载均衡]]></category>
		<category><![CDATA[跨界学习]]></category>
		<category><![CDATA[运维成本]]></category>
		<category><![CDATA[迷雾]]></category>
		<category><![CDATA[道]]></category>
		<category><![CDATA[重修基础]]></category>
		<category><![CDATA[重启大法]]></category>
		<category><![CDATA[阅读源码]]></category>
		<category><![CDATA[降维打击]]></category>
		<category><![CDATA[难以迁移]]></category>
		<category><![CDATA[顶尖程序员]]></category>
		<category><![CDATA[高可用]]></category>
		<category><![CDATA[高并发]]></category>
		<category><![CDATA[高级语言]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=5304</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/10/24/from-fanren-to-three-body-top-programmers-power 大家好，我是Tony Bai。 在上篇文章中，我们论道了程序员的修仙境界。但一个更深层的问题随之而来：决定一个修士（程序员）最终高度的，究竟是什么？是掌握了更多华丽的“法术”（框架/工具），还是洞悉了其背后的“天地法则”（底层原理）？ 在《凡人修仙传》的后期，韩天尊与道祖们的斗法，早已不是简单的法宝对轰，而是对时间、空间等“至尊法则”的掌控。谁对法则的理解更深，谁就能言出法随，改天换地。 这正如《三体》中的高等文明，它们不屑于用飞船、激光炮甚至核武器，而是直接动用宇宙规律本身作为武器——一张“二向箔”，便能将整个太阳系从三维降至二维，完成终极的“降维打击”。 回到我们的世界，程序员的“降维打击”又是什么？答案是：当大多数人还在钻研“术”（框架、API）的层面时，顶尖高手早已在运用“道”（计算机科学基础法则）的力量，直击问题的本源。 这“术”与“道”的差别，便在程序员的成长之路上，自然而然地分化出了两条截然不同的修行路线。一条是精研万千“法术”，追求招式的极致与华丽；另一条则是追本溯源，探寻那不变的“天地大道”。 接下来，就让我们一同探寻这两条路上的风景，看看它们各自通往何方。 “修术”与“悟道”：程序员的两条修行之路 程序员的成长，往往会分化为两条截然不同的修行路线。 第一条路：“修术”的修士 —— 框架与API的熟练工 在修仙界，他们是勤学苦练各种“法术”的低阶修士，对“火球术”、“御风术”的咒语手诀了如指掌，能在战斗中熟练释放。但他们不知火球为何燃烧，当遇到克制其法术的敌人时，便会束手无策。 在程序员界，他们是这样的： 特征： 精通 Gin/Spring/Vue/React 全家桶，对各种注解、Hook、API 信手拈来，能用极高的效率搭建业务应用。他们是项目中的“突击手”，是团队快速交付的保障。 瓶颈： 知其然，不知其所以然： 遇到深层次问题，如 JVM 内存溢出、GC 频繁、数据库死锁时，他们的“法术”失灵了。因为这些问题触及了“术”背后的“法则”。 根基不稳，难以迁移： 当技术浪潮更迭，新的框架（新的“法术体系”）出现时，他们需要从头学起，过去的经验很大一部分会作废。 天花板低： 他们的工作是“实现”，而非“创造”。他们能用积木搭出华丽的城堡，但无法自己设计和制造积木。 第二条路：“悟道”的宗师 —— 法则与本源的掌控者 在修仙界，他们是韩立后期的境界，乃至道祖。他们不再拘泥于具体“法术”，想用火，便直接调动天地间的火之法则。他们甚至可以“神通自创”，因为他们理解了力量的本源。 在程序员界，他们掌握了那些不变的“法则”： 时间法则 -> 算法与复杂度： 他们深知，程序的性能瓶颈往往不在于硬件快慢，而在于算法的优劣。一个从 O(n²) 到 O(n log n) 的算法优化，胜过十倍的服务器升级。这是对程序“时间流速”的直接掌控。 空间法则 -> 数据结构与内存管理： 他们能清晰地看到数据在内存中的排布，理解缓存行（Cache Line）、指针跳转如何影响性能。他们选择数据结构，如同仙人布置洞府，每一寸空间都物尽其用。这是对计算机“物理空间”的精妙运用。 构造法则 -> [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/from-fanren-to-three-body-top-programmers-power-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/10/24/from-fanren-to-three-body-top-programmers-power">本文永久链接</a> &#8211; https://tonybai.com/2025/10/24/from-fanren-to-three-body-top-programmers-power</p>
<p>大家好，我是Tony Bai。</p>
<p>在上篇文章中，我们论道了<a href="https://tonybai.com/2025/09/08/fanren-xiuxian-programmer-levels">程序员的修仙境界</a>。但一个更深层的问题随之而来：决定一个修士（程序员）最终高度的，究竟是什么？是掌握了更多华丽的“法术”（框架/工具），还是洞悉了其背后的“天地法则”（底层原理）？</p>
<p>在《凡人修仙传》的后期，韩天尊与道祖们的斗法，早已不是简单的法宝对轰，而是对时间、空间等“至尊法则”的掌控。谁对法则的理解更深，谁就能言出法随，改天换地。</p>
<p>这正如《三体》中的高等文明，它们不屑于用飞船、激光炮甚至核武器，而是直接动用宇宙规律本身作为武器——一张“二向箔”，便能将整个太阳系从三维降至二维，完成终极的“降维打击”。</p>
<p>回到我们的世界，程序员的“降维打击”又是什么？答案是：<strong>当大多数人还在钻研“术”（框架、API）的层面时，顶尖高手早已在运用“道”（计算机科学基础法则）的力量，直击问题的本源。</strong></p>
<p>这“术”与“道”的差别，便在程序员的成长之路上，自然而然地分化出了两条截然不同的修行路线。一条是精研万千“法术”，追求招式的极致与华丽；另一条则是追本溯源，探寻那不变的“天地大道”。</p>
<p>接下来，就让我们一同探寻这两条路上的风景，看看它们各自通往何方。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/go-network-programming-complete-guide-pr.png" alt="" /></p>
<h2>“修术”与“悟道”：程序员的两条修行之路</h2>
<p>程序员的成长，往往会分化为两条截然不同的修行路线。</p>
<h3>第一条路：“修术”的修士 —— 框架与API的熟练工</h3>
<p><img src="https://tonybai.com/wp-content/uploads/2025/from-fanren-to-three-body-top-programmers-power-2.png" alt="" /></p>
<p>在修仙界，他们是勤学苦练各种“法术”的低阶修士，对“火球术”、“御风术”的咒语手诀了如指掌，能在战斗中熟练释放。但他们不知火球为何燃烧，当遇到克制其法术的敌人时，便会束手无策。</p>
<p>在程序员界，他们是这样的：</p>
<ul>
<li><strong>特征：</strong> 精通 Gin/Spring/Vue/React 全家桶，对各种注解、Hook、API 信手拈来，能用极高的效率搭建业务应用。他们是项目中的“突击手”，是团队快速交付的保障。</li>
<li><strong>瓶颈：</strong>
<ol>
<li><strong>知其然，不知其所以然：</strong> 遇到深层次问题，如 JVM 内存溢出、GC 频繁、数据库死锁时，他们的“法术”失灵了。因为这些问题触及了“术”背后的“法则”。</li>
<li><strong>根基不稳，难以迁移：</strong> 当技术浪潮更迭，新的框架（新的“法术体系”）出现时，他们需要从头学起，过去的经验很大一部分会作废。</li>
<li><strong>天花板低：</strong> 他们的工作是“实现”，而非“创造”。他们能用积木搭出华丽的城堡，但无法自己设计和制造积木。</li>
</ol>
</li>
</ul>
<h3>第二条路：“悟道”的宗师 —— 法则与本源的掌控者</h3>
<p><img src="https://tonybai.com/wp-content/uploads/2025/from-fanren-to-three-body-top-programmers-power-3.png" alt="" /></p>
<p>在修仙界，他们是韩立后期的境界，乃至道祖。他们不再拘泥于具体“法术”，想用火，便直接调动天地间的火之法则。他们甚至可以“神通自创”，因为他们理解了力量的本源。</p>
<p>在程序员界，他们掌握了那些不变的“法则”：</p>
<ul>
<li>
<p><strong>时间法则 -> 算法与复杂度：</strong> 他们深知，程序的性能瓶颈往往不在于硬件快慢，而在于算法的优劣。一个从 O(n²) 到 O(n log n) 的算法优化，胜过十倍的服务器升级。这是对程序“时间流速”的直接掌控。</p>
</li>
<li>
<p><strong>空间法则 -> 数据结构与内存管理：</strong> 他们能清晰地看到数据在内存中的排布，理解缓存行（Cache Line）、指针跳转如何影响性能。他们选择数据结构，如同仙人布置洞府，每一寸空间都物尽其用。这是对计算机“物理空间”的精妙运用。</p>
</li>
<li>
<p><strong>构造法则 -> 计算机体系结构与编译原理：</strong> 他们明白每一行高级语言，最终是如何被翻译成机器指令，在 CPU 的流水线上执行的。这种知识让他们能写出“亲和硬件”的代码，榨干硬件的每一分潜力。</p>
</li>
<li>
<p><strong>因果法则 -> 计算机网络与分布式理论：</strong> 他们对网络的延迟、不可靠性有着深刻的敬畏。在设计系统时，他们遵循 CAP、BASE 等“因果铁律”，而不是盲目追求不可能的“既要又要”。</p>
</li>
</ul>
<h2>法则之力：程序员的“降维打击”</h2>
<p>当“修术者”遇到瓶颈时，“悟道者”便会展现出碾压性的“降维打击”。</p>
<h3>场景一：性能优化之战</h3>
<ul>
<li><strong>修术者：</strong> “系统慢了！赶紧加缓存！上 Redis！不行就升级服务器，从4核8G干到16核32G！”</li>
<li><strong>悟道者：</strong> “我先用 profiler 分析一下。哦，原来是这里有一个嵌套循环导致了笛卡尔积。把数据结构换成哈希表，一次遍历解决。”</li>
<li><strong>结果：</strong> <strong>这是智力对算力的降维打击。</strong></li>
</ul>
<h3>场景二：诡异 Bug 排除</h3>
<ul>
<li><strong>修术者：</strong> “这个 Bug 时有时无，只在生产环境高并发下出现！肯定是框架的 Bug！玄学，先重启大法试试。”</li>
<li><strong>悟道者：</strong> “听起来像是线程安全问题。我检查一下这里的共享变量，果然没有加锁，导致了竞态条件（Race Condition）。或者，这可能是 GC 停顿引起的。”</li>
<li><strong>结果：</strong> <strong>这是洞察力对试错法的降维打击。</strong></li>
</ul>
<h3>场景三：技术选型决策</h3>
<ul>
<li><strong>修术者：</strong> “我们要做新项目！必须用现在最火的微服务架构！上 Service Mesh，上云原生全家桶！”</li>
<li><strong>悟道者：</strong> “我们的业务初期流量不大，团队规模也小，强上微服务会带来巨大的运维成本。一个设计良好的单体应用，更能满足当前阶段的需求。要敬畏分布式系统的因果法则。”</li>
<li><strong>结果：</strong> <strong>这是第一性原理对盲目跟风的降维打击。</strong></li>
</ul>
<h2>如何“悟道”：从“术”到“道”的修行之路</h2>
<p>“悟道”之路，注定是艰难而孤独的，但也是回报最丰厚的。</p>
<ol>
<li>
<p><strong>心法总纲：保持好奇，永远追问“为什么？”</strong><br />
当你在用一个注解时，问自己：它背后是通过什么机制实现的？不要满足于“它能工作”，要去探寻“它为何能这样工作”。</p>
</li>
<li>
<p><strong>具体功法：</strong></p>
<ul>
<li><strong>重修基础，稳固道基：</strong> 静下心来，去啃那些“无用”的经典。《深入理解计算机系统》(CSAPP)、《算法导论》、《TCP/IP详解》……这些是刻在石头上的“天地法则”，是所有“法术”的根基。</li>
<li><strong>阅读源码，洞悉法术本源：</strong> 去读 Gin、Spring、Netty、Redis 的源码。看懂它们，就像是亲眼目睹了一位炼器大师如何将基础材料炼制成一件惊世法宝。</li>
<li><strong>动手造轮子，亲身证道：</strong> 尝试自己写一个简单的 Web 服务器、一个 RPC 框架。在这个过程中，你会被迫直面那些“法则”，并想办法去驾驭它们。</li>
<li><strong>跨界学习，他山之石：</strong> 学习数学、物理学、控制论中的思想。你会发现，负载均衡的思想在经济学中有体现，高可用的设计哲学与生物学的冗余备份异曲同工。大道相通。</li>
</ul>
</li>
</ol>
<h2>小结</h2>
<p>从“修术”到“悟道”，不是一条非此即彼的道路，而是一个螺旋上升的过程。我们始于“术”，在实践中不断碰壁，从而激发对“道”的渴望；悟“道”之后，我们能更好地驾驭和创造新的“术”。</p>
<p>在程序员的修行世界里，“修术”可以让你成为一名可靠的工程师，在宗门（公司）里安身立命。但唯有“悟道”，才能让你拥有穿越技术周期、直击问题本质的力量，成为真正定义未来的宗师，施展出属于你的“降维打击”。</p>
<p>愿你我都能在代码的修行中，拨开“术”的迷雾，窥见“道”的光芒。</p>
<hr />
<p>你的Go技能，是否也卡在了“熟练”到“精通”的瓶颈期？</p>
<ul>
<li>想写出更地道、更健壮的Go代码，却总在细节上踩坑？</li>
<li>渴望提升软件设计能力，驾驭复杂Go项目却缺乏章法？</li>
<li>想打造生产级的Go服务，却在工程化实践中屡屡受挫？</li>
</ul>
<p>继《<a href="http://gk.link/a/10AVZ">Go语言第一课</a>》后，我的《<a href="http://gk.link/a/12yGY">Go语言进阶课</a>》终于在极客时间与大家见面了！</p>
<p>我的全新极客时间专栏 《<a href="http://gk.link/a/12yGY">Tony Bai·Go语言进阶课</a>》就是为这样的你量身打造！30+讲硬核内容，带你夯实语法认知，提升设计思维，锻造工程实践能力，更有实战项目串讲。</p>
<p>目标只有一个：助你完成从“Go熟练工”到“Go专家”的蜕变！ 现在就加入，让你的Go技能再上一个新台阶！</p>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<hr />
<p><strong>想系统学习Go，构建扎实的知识体系？</strong></p>
<p>我的新书《<a href="https://book.douban.com/subject/37499496/">Go语言第一课</a>》是你的首选。源自2.4万人好评的极客时间专栏，内容全面升级，同步至Go 1.24。首发期有专属五折优惠，不到40元即可入手，扫码即可拥有这本300页的Go语言入门宝典，即刻开启你的Go语言高效学习之旅！</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/go-primer-published-4.png" alt="" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/10/24/from-fanren-to-three-body-top-programmers-power/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>“包管理器是万恶之源”：一次来自Odin语言作者的灵魂拷问</title>
		<link>https://tonybai.com/2025/09/13/package-managers-are-evil/</link>
		<comments>https://tonybai.com/2025/09/13/package-managers-are-evil/#comments</comments>
		<pubDate>Fri, 12 Sep 2025 23:48:48 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[Batteries-Included]]></category>
		<category><![CDATA[CodeGeneration]]></category>
		<category><![CDATA[CodeQuality]]></category>
		<category><![CDATA[CommunityActivity]]></category>
		<category><![CDATA[ComplexDependencies]]></category>
		<category><![CDATA[DependencyHell]]></category>
		<category><![CDATA[DependencyTree]]></category>
		<category><![CDATA[EngineeringPractices]]></category>
		<category><![CDATA[Gell-Mann Amnesia Effect]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[gomodule]]></category>
		<category><![CDATA[GoProverb]]></category>
		<category><![CDATA[Liability]]></category>
		<category><![CDATA[MaintenanceStatus]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[PackageManagers]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[standardlibrary]]></category>
		<category><![CDATA[代码生成]]></category>
		<category><![CDATA[代码质量]]></category>
		<category><![CDATA[依赖地狱]]></category>
		<category><![CDATA[依赖树]]></category>
		<category><![CDATA[包管理器]]></category>
		<category><![CDATA[复杂依赖]]></category>
		<category><![CDATA[工程化]]></category>
		<category><![CDATA[标准库]]></category>
		<category><![CDATA[盖尔曼遗忘效应]]></category>
		<category><![CDATA[社区活跃度]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[维护状态]]></category>
		<category><![CDATA[自动化]]></category>
		<category><![CDATA[自带电池]]></category>
		<category><![CDATA[负债]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=5154</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/09/13/package-managers-are-evil 大家好，我是Tony Bai。 “包管理器是万恶之源 (Package Managers are Evil)。” 这句石破天惊的论断，出自Odin语言的创造者Ginger Bill最近发表的一篇博文。在一个npm install、pip install、go get已经成为开发者肌肉记忆的时代，这无异于一篇挑战整个现代软件开发基石的“檄文”。 对于我们这些深度依赖go mod的Gopher来说，这无疑也是一次直击灵魂的拷问。我们早已习惯了Go Modules带来的便利——它解决了版本锁定、依赖传递和可复现构建等核心问题，被公认为Go生态走向成熟的里程碑。但我们是否在享受便利的同时，也正在“自动化我们的依赖地狱”？ Ginger Bill的这篇文章并非无的放矢的抱怨，而是一次对开发者文化、信任模型和软件工程第一性原理的深刻反思。让我们直面这次拷问，并以此为镜，重新审视我们与go mod的关系。 核心论点：包管理器是“依赖地狱的自动化” 首先，Ginger Bill做了一个关键的区分，他的矛头并非指向： 包（Packages）: 代码组织单元。 仓库（Repositories）: 发现和存储包的地方（如GitHub）。 构建系统（Build Systems）: 编译和链接代码的工具。 他精准地将炮火对准了包管理器（Package Managers）的核心功能：自动化地下载、解析和处理依赖关系。 他认为，这正是问题的根源所在。“依赖地狱”（Dependency Hell）是一个真实存在的、困扰着所有大型项目的难题——成千上万个你并不真正了解的传递依赖，版本冲突、潛在的bug、未知的安全漏洞，共同构成了一个巨大的泥潭。 而包管理器的作用，就是“将这个通往地狱的过程自动化了”。 他辛辣地指出：“不是所有能被自动化的东西，都应该被自动化，尤其是依赖地狱。” 他的核心观点是，npm install或go get这种一键式的便利，剥夺了开发者一个至关重要的环节：思考。 “当你必须手动下载和集成一个库时，你会开始思考：‘我也许并不需要这个’，或者‘我可以用别的方式来实现’。当需要更新时，手动操作会迫使你变得非常小心。” 这种被刻意放慢的、充满“摩擦力”的过程，迫使开发者去审视每一个引入的依赖，将其视为一个严肃的决策，而不是一次随意的命令行敲击。 Go的悖论：一个“幸免于难”的生态？ 有趣的是，在Ginger Bill的批判中，Go被作为一个相对正面的例子提及。他观察到，即便Go拥有一个内置的包管理器，但大多数Go开发者似乎并不需要引入大量的第三方包。 “通往地狱的入口似乎又远又难走。” 为什么Go生态在一定程度上抵御了其他生态（如JavaScript）中那种失控的依赖爆炸？答案在于Go语言的设计哲学：“自带电池”（Batteries Included）。 Go拥有一个极其强大和全面的标准库。你想构建一个高性能的Web服务器？net/http就在那里。你需要处理JSON、加密、模板或者并发？标准库为你提供了一流的、经过实战检验的工具。你甚至可以在标准库里找到一个完整的Go编译器。 这种设计极大地降低了对外部微小、功能单一的“工具包”的依赖。当标准库就能满足80%的需求时，开发者自然不会像在其他生态中那样，为了实现一个最基本的功能（比如left-pad）就去引入一个外部依赖。 然而，这并不意味着Go开发者可以高枕无忧。go mod依然是一个强大的自动化工具，当我们开始引入大型框架（如Gin、GORM）或复杂的SDK时，我们同样面临着瞬间引入数十甚至上百个传递依赖的风险。 每一个依赖，都是你签下的一份“责任状” 文章中最深刻的观点之一，是对“依赖”一词含义的重新诠释。 “在现实生活中，当你有一个依赖时，你要对它负责。如果你的孩子或你的公司做错了事，你可能会因此进监狱。包依赖与此相去不远，但人们却在几乎没有任何验证的情况下就信任了它们。” [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/package-managers-are-evil-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/09/13/package-managers-are-evil">本文永久链接</a> &#8211; https://tonybai.com/2025/09/13/package-managers-are-evil</p>
<p>大家好，我是Tony Bai。</p>
<blockquote>
<p>“包管理器是万恶之源 (Package Managers are Evil)。”</p>
</blockquote>
<p>这句石破天惊的论断，出自<a href="https://odin-lang.org/">Odin语言</a>的创造者<a href="https://www.gingerbill.org/article/2025/09/08/package-managers-are-evil/">Ginger Bill最近发表的一篇博文</a>。在一个npm install、pip install、go get已经成为开发者肌肉记忆的时代，这无异于一篇挑战整个现代软件开发基石的“檄文”。</p>
<p>对于我们这些深度依赖go mod的Gopher来说，这无疑也是一次直击灵魂的拷问。我们早已习惯了Go Modules带来的便利——它解决了版本锁定、依赖传递和可复现构建等核心问题，被公认为Go生态走向成熟的里程碑。但我们是否在享受便利的同时，也正在“自动化我们的依赖地狱”？</p>
<p>Ginger Bill的这篇文章并非无的放矢的抱怨，而是一次对开发者文化、信任模型和软件工程第一性原理的深刻反思。让我们直面这次拷问，并以此为镜，重新审视我们与go mod的关系。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/go-micro-column-2025-pr.png" alt="" /></p>
<h2>核心论点：包管理器是“依赖地狱的自动化”</h2>
<p>首先，Ginger Bill做了一个关键的区分，他的矛头并非指向：</p>
<ul>
<li><strong>包（Packages）</strong>: 代码组织单元。</li>
<li><strong>仓库（Repositories）</strong>: 发现和存储包的地方（如GitHub）。</li>
<li><strong>构建系统（Build Systems）</strong>: 编译和链接代码的工具。</li>
</ul>
<p>他精准地将炮火对准了<strong>包管理器（Package Managers）</strong>的核心功能：<strong>自动化地下载、解析和处理依赖关系。</strong></p>
<p>他认为，这正是问题的根源所在。<strong>“依赖地狱”（Dependency Hell）</strong>是一个真实存在的、困扰着所有大型项目的难题——成千上万个你并不真正了解的传递依赖，版本冲突、潛在的bug、未知的安全漏洞，共同构成了一个巨大的泥潭。</p>
<p>而包管理器的作用，就是<strong>“将这个通往地狱的过程自动化了”</strong>。</p>
<p>他辛辣地指出：“不是所有能被自动化的东西，都应该被自动化，尤其是依赖地狱。”</p>
<p>他的核心观点是，npm install或go get这种一键式的便利，剥夺了开发者一个至关重要的环节：<strong>思考</strong>。</p>
<blockquote>
<p>“当你必须手动下载和集成一个库时，你会开始思考：‘我也许并不需要这个’，或者‘我可以用别的方式来实现’。当需要更新时，手动操作会迫使你变得非常小心。”</p>
</blockquote>
<p>这种被刻意放慢的、充满“摩擦力”的过程，迫使开发者去审视每一个引入的依赖，将其视为一个严肃的决策，而不是一次随意的命令行敲击。</p>
<h2>Go的悖论：一个“幸免于难”的生态？</h2>
<p>有趣的是，在Ginger Bill的批判中，Go被作为一个相对正面的例子提及。他观察到，即便Go拥有一个内置的包管理器，但大多数Go开发者似乎并不需要引入大量的第三方包。</p>
<blockquote>
<p>“通往地狱的入口似乎又远又难走。”</p>
</blockquote>
<p>为什么Go生态在一定程度上抵御了其他生态（如JavaScript）中那种失控的依赖爆炸？答案在于Go语言的设计哲学：<strong>“自带电池”（Batteries Included）</strong>。</p>
<p>Go拥有一个极其强大和全面的标准库。你想构建一个高性能的Web服务器？net/http就在那里。你需要处理JSON、加密、模板或者并发？标准库为你提供了一流的、经过实战检验的工具。你甚至可以在标准库里找到一个完整的Go编译器。</p>
<p>这种设计极大地降低了对外部微小、功能单一的“工具包”的依赖。当标准库就能满足80%的需求时，开发者自然不会像在其他生态中那样，为了实现一个最基本的功能（比如left-pad）就去引入一个外部依赖。</p>
<p>然而，这并不意味着Go开发者可以高枕无忧。go mod依然是一个强大的自动化工具，当我们开始引入大型框架（如Gin、GORM）或复杂的SDK时，我们同样面临着瞬间引入数十甚至上百个传递依赖的风险。</p>
<h2>每一个依赖，都是你签下的一份“责任状”</h2>
<p>文章中最深刻的观点之一，是对“依赖”一词含义的重新诠释。</p>
<blockquote>
<p>“在现实生活中，当你有一个依赖时，你要对它负责。如果你的孩子或你的公司做错了事，你可能会因此进监狱。包依赖与此相去不远，但人们却在几乎没有任何验证的情况下就信任了它们。”</p>
</blockquote>
<p>每一个go get下来的包，都是一份你自愿承担的<strong>负债</strong>。你不仅要为它的安全漏洞负责，还要为它的bug、为它未来可能停止维护的风险负责。</p>
<p>作者以他自己使用著名C库SDL2的痛苦经历为例。尽管SDL2被数百万人使用，但他的团队却不断踩到其中的bug，最终决定自己从头编写窗口和输入处理系统。“至少这是我们自己的代码，当出问题时我们可以依赖和修复它。”</p>
<p><strong>“我不是在提倡一切都从头造轮子，”</strong> 作者澄清道，“我只是希望我们能认识到，每一个依赖都是一份负债。”</p>
<h2>文化反思：程序员世界里的“盖尔曼遗忘效应”</h2>
<p>为什么我们会如此轻易地信任来自互联网的随机代码？文章引用了ThePrimeagen的一个精彩论点：<strong>编程界的“盖尔曼遗忘效应”（Gell-Mann Amnesia Effect）</strong>。</p>
<p>这个效应描述了一种现象：当你在报纸上读到一篇关于你所精通领域的文章时（比如马术），你会发现其中充满了错误和误解。然后，你翻到下一页，读到一篇关于你不了解的领域（比如JavaScript）的文章，你又会理所当然地认为它是完全正确的。你瞬间忘记了刚刚才亲身验证过的、媒体的不可靠性。</p>
<p>程序员也存在同样的问题：</p>
<blockquote>
<p>“你会发现工程师们一边说‘我的一些同事太可怕了’，一边又说‘嘿，让我从网上下载这个库，这肯定很棒’。他们看着自己公司三分之一的员工无法写出像样的代码，同时又选择信任他们下载的每一个开源包。”</p>
</blockquote>
<p>我们对自己身边代码的质量持怀疑态度，却对那些由“开源大神”（他们可能和我们糟糕的同事是同一水平）编写的代码抱有不切实际的、过高的信任。</p>
<h2>小结：给Gopher的启示——如何与go mod共存？</h2>
<p>Ginger Bill的结论是激进的：如果可能，应该避免使用包管理器。对于大多数在团队中工作的Go开发者来说，这显然是不现实的。go mod是Go生态协作的基石，我们不可能回到手动管理依赖的蛮荒时代。</p>
<p>然而，这篇文章的价值不在于它的结论，而在于它提出的<strong>哲学框架</strong>。它像一面镜子，让我们反思我们与go mod的关系。我们可以从中提炼出几条适用于Gopher的行动指南：</p>
<ol>
<li><strong>将go get视为一个严肃的架构决策</strong>：在引入任何新的依赖之前，进行尽职调查。检查它的代码质量、社区活跃度、issue列表和维护状态，虽然这会给你带来不小的额外工作量。</li>
<li><strong>永远优先选择标准库</strong>：在寻求外部解决方案之前，先问自己：“这个问题，std库里真的没有解决方案吗？” 往往答案是有的，只是需要你多花一点时间去挖掘。</li>
<li><strong>适当优先地拥抱代码生成，而非黑盒框架</strong>：在某些场景下，使用代码生成工具（如sqlc）可能比引入一个庞大的ORM框架（它会带来一整套复杂的依赖和抽象）更“简单”，因为它产出的是你可以直接阅读和控制的代码。</li>
<li><strong>定期审计你的依赖树</strong>：使用go mod graph和go list -m all来审视你的项目究竟依赖了什么。对于那些不再需要，或者有更好替代品的依赖，要勇于清理。别忘了<a href="https://go-proverbs.github.io/">Go Proverbs</a>中的那一条：A little copying is better than a little dependency。</li>
</ol>
<p>Go的“自带电池”哲学给了我们一个得天独厚的优势，让我们能更容易地践行“少即是多”的依赖管理原则。<strong>最好的包管理器，或许就是那个你用得最少的。</strong> 而go mod的真正强大之处，可能不在于它能多么轻易地帮我们添加依赖，而在于它通过一个强大的标准库，让我们在很多时候，根本无需想起它。</p>
<hr />
<p><strong>想系统学习Go，构建扎实的知识体系？</strong></p>
<p>我的新书《<a href="https://book.douban.com/subject/37499496/">Go语言第一课</a>》是你的首选。源自2.4万人好评的极客时间专栏，内容全面升级，同步至Go 1.24。首发期有专属五折优惠，不到40元即可入手，扫码即可拥有这本300页的Go语言入门宝典，即刻开启你的Go语言高效学习之旅！</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/go-primer-published-4.png" alt="" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/09/13/package-managers-are-evil/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>从《凡人修仙传》看程序员境界：道友，你修炼到哪一层了？</title>
		<link>https://tonybai.com/2025/09/08/fanren-xiuxian-programmer-levels/</link>
		<comments>https://tonybai.com/2025/09/08/fanren-xiuxian-programmer-levels/#comments</comments>
		<pubDate>Mon, 08 Sep 2025 00:07:54 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Architect]]></category>
		<category><![CDATA[Ascension]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[CareerDevelopment]]></category>
		<category><![CDATA[Coder]]></category>
		<category><![CDATA[Codereview]]></category>
		<category><![CDATA[CoreFormation]]></category>
		<category><![CDATA[CRUD]]></category>
		<category><![CDATA[CTO]]></category>
		<category><![CDATA[Cultivation]]></category>
		<category><![CDATA[DatabaseOptimization]]></category>
		<category><![CDATA[DistributedSystems]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[FoundationEstablishment]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[HighConcurrency]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JuniorEngineer]]></category>
		<category><![CDATA[k8s]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[LeetCode]]></category>
		<category><![CDATA[LevelDivision]]></category>
		<category><![CDATA[mapreduce]]></category>
		<category><![CDATA[MidlevelEngineer]]></category>
		<category><![CDATA[NascentSoul]]></category>
		<category><![CDATA[Opensource]]></category>
		<category><![CDATA[PrincipalEngineer]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[ProgrammerLevels]]></category>
		<category><![CDATA[programminglanguage]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[QiRefining]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[SeniorEngineer]]></category>
		<category><![CDATA[SoftwareEngineer]]></category>
		<category><![CDATA[SpiritTransformation]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Stackoverflow]]></category>
		<category><![CDATA[SystemArchitecture]]></category>
		<category><![CDATA[TechLead]]></category>
		<category><![CDATA[TechnicalDebt]]></category>
		<category><![CDATA[TechnicalStandard]]></category>
		<category><![CDATA[TechSharing]]></category>
		<category><![CDATA[TensorFlow]]></category>
		<category><![CDATA[Vue]]></category>
		<category><![CDATA[修仙]]></category>
		<category><![CDATA[元婴]]></category>
		<category><![CDATA[凡人修仙传]]></category>
		<category><![CDATA[分布式]]></category>
		<category><![CDATA[化神]]></category>
		<category><![CDATA[境界划分]]></category>
		<category><![CDATA[开源]]></category>
		<category><![CDATA[技术债务]]></category>
		<category><![CDATA[技术分享]]></category>
		<category><![CDATA[技术大牛]]></category>
		<category><![CDATA[技术规范]]></category>
		<category><![CDATA[数据库优化]]></category>
		<category><![CDATA[架构师]]></category>
		<category><![CDATA[框架]]></category>
		<category><![CDATA[炼气]]></category>
		<category><![CDATA[码农]]></category>
		<category><![CDATA[神识]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[程序员境界]]></category>
		<category><![CDATA[筑基]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[结丹]]></category>
		<category><![CDATA[编程语言]]></category>
		<category><![CDATA[职业发展]]></category>
		<category><![CDATA[走火入魔]]></category>
		<category><![CDATA[软件工程师]]></category>
		<category><![CDATA[造轮子]]></category>
		<category><![CDATA[韩立]]></category>
		<category><![CDATA[飞升]]></category>
		<category><![CDATA[首席工程师]]></category>
		<category><![CDATA[高并发]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=5131</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2025/09/08/fanren-xiuxian-programmer-levels 大家好，我是Tony Bai。 最近《凡人修仙传》的电视剧大火，想必各位道友都有耳闻。鄙人也没忍住，不仅刷完了杨洋主演的网剧，还趁着这股热乎劲儿，一口气在微信读书连读再听地补完了小说的人界篇。 当看到韩立资质平平，相貌普通，却凭着“小绿瓶”、远超常人的心智和不懈的努力，在残酷的修仙界中，历经炼气、筑基、结丹、元婴，终至化神时，我猛然拍案： 这不就是我们程序员升级打怪的真实写照吗？！ 仔细一想，还真是如此。在这“码农”修仙界，人人皆望飞升，脱离 CRUD 的苦海，证得架构大道。韩天尊从一介凡人，在人界一步步逆天修行；我们则从一行“Hello World”开始，在代码的世界里摸爬滚打。从初窥门径到执掌乾坤，其间的艰辛与突破，又何尝不是一场惊心动魄的修行？ 今日，不妨让我们借韩天尊的人界飞升之路，一同探寻这程序员的修仙境界。看看你我，如今身在何处，又该如何“破境”飞升。 第一境：炼气期 &#8211; 程序员学徒 炼气期 此境界的修士初入仙门，刚刚感应到“天地灵气”（编程语言），开始学习吐纳之法（基础语法）。灵力微薄，法术生疏，面对浩如烟海的功法秘籍（API文档），常常感到力不从心，一不小心就可能“走火入魔”（写出 Bug）。 境界特征： 初窥门径，灵力微薄： 刚掌握一门或多门“功法”（Java/Python/Go），但理解不深。能写出基础的业务逻辑，但对底层原理一知半解，如同只会念咒却不知其所以然。 修炼功法，打牢根基： 每日勤修不辍，疯狂“吸收灵石”（看文档、刷 LeetCode、学习框架）。主要任务是完成导师（Mentor）分配的“宗门任务”（小功能、Bug修复），以此换取修炼资源。 依赖法器，难离其身： 严重依赖各种“低阶法器”，如 Stack Overflow、CSDN 和各类 AI 代码助手。一旦“法器”失灵（断网），便束手无策，战力大减。 心魔与瓶颈： 最大的心魔是“我是不是不适合写代码”的自我怀疑。常常会遇到“瓶颈”，一个简单的 Bug 可能要耗费数日才能解决，此时急需一颗“筑基丹”（高人指点）方能突破。 第二境：筑基期 &#8211; 合格的工程师 筑基期 经历无数次“走火入魔”后，终于炼化灵气，开辟丹田，成功“筑基”，体内的“灵力”（知识体系）凝聚成形。从此，你不再是修仙界的炮灰，而是一名真正的修士，可以独立执行任务，在宗门（团队）中有了一席之地。 境界特征： 筑基成功，道途有望： 能够独立负责一个模块或一条业务线。对团队的技术栈了如指掌，是项目的中坚力量，道基稳固。 拥有本命法器： 不再是见什么用什么，而是有了自己得心应手的“本命法器”（精通的框架或工具链），如 Spring 全家桶、Vue/React 生态。使用起来得心应手，威力倍增。 神识初成，洞察秋毫： 开始具备一定的“神识”（Code Review 能力和设计嗅觉），能发现炼气期修士代码中的明显问题，并预见一些潜在的风险，如同神识外放，探查四周。 独立执行宗门任务： 可以独立外出执行有一定难度的“宗门任务”（负责一个完整需求），并能顺利归来，不再需要师兄寸步不离地看护。 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/2025/fanren-xiuxian-programmer-levels-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2025/09/08/fanren-xiuxian-programmer-levels">本文永久链接</a> &#8211; https://tonybai.com/2025/09/08/fanren-xiuxian-programmer-levels</p>
<p>大家好，我是Tony Bai。</p>
<p>最近《凡人修仙传》的电视剧大火，想必各位道友都有耳闻。鄙人也没忍住，不仅刷完了杨洋主演的网剧，还趁着这股热乎劲儿，一口气在微信读书连读再听地补完了小说的人界篇。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/fanren-xiuxian-programmer-levels-0.png" alt="" /></p>
<p>当看到韩立资质平平，相貌普通，却凭着“小绿瓶”、远超常人的心智和不懈的努力，在残酷的修仙界中，历经<strong>炼气、筑基、结丹、元婴，终至化神</strong>时，我猛然拍案：</p>
<p><strong>这不就是我们程序员升级打怪的真实写照吗？！</strong></p>
<p>仔细一想，还真是如此。在这“码农”修仙界，人人皆望飞升，脱离 CRUD 的苦海，证得<a href="https://tonybai.com/2025/08/25/documents-the-architects-programming-language/">架构大道</a>。韩天尊从一介凡人，在人界一步步逆天修行；我们则从一行“Hello World”开始，在代码的世界里摸爬滚打。从初窥门径到执掌乾坤，其间的艰辛与突破，又何尝不是一场惊心动魄的修行？</p>
<p>今日，不妨让我们借韩天尊的人界飞升之路，一同探寻这程序员的修仙境界。看看你我，如今身在何处，又该如何“破境”飞升。</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/paid/go-micro-column-2025-pr.png" alt="" /></p>
<h2>第一境：炼气期 &#8211; 程序员学徒</h2>
<p><img src="https://tonybai.com/wp-content/uploads/2025/fanren-xiuxian-programmer-levels-2.png" alt="" /><br />
<center>炼气期</center></p>
<p>此境界的修士初入仙门，刚刚感应到“天地灵气”（<a href="https://tonybai.com/2024/10/24/cognitive-load-impact-on-programming-language-choice-and-study">编程语言</a>），开始学习吐纳之法（<a href="https://tonybai.com/2024/08/27/a-new-syntax-quiz-after-go-1-18/">基础语法</a>）。灵力微薄，法术生疏，面对浩如烟海的功法秘籍（<a href="https://tonybai.com/2025/07/14/writing-style-guide">API文档</a>），常常感到力不从心，一不小心就可能“走火入魔”（写出 Bug）。</p>
<ul>
<li><strong>境界特征：</strong>
<ul>
<li><strong>初窥门径，灵力微薄：</strong> 刚掌握一门或多门“功法”（Java/Python/Go），但理解不深。能写出基础的业务逻辑，但对底层原理一知半解，如同只会念咒却不知其所以然。</li>
<li><strong>修炼功法，打牢根基：</strong> 每日勤修不辍，疯狂“吸收灵石”（看文档、刷 LeetCode、学习框架）。主要任务是完成导师（Mentor）分配的“宗门任务”（小功能、Bug修复），以此换取修炼资源。</li>
<li><strong>依赖法器，难离其身：</strong> 严重依赖各种“低阶法器”，如 Stack Overflow、CSDN 和各类 AI 代码助手。一旦“法器”失灵（断网），便束手无策，战力大减。</li>
<li><strong>心魔与瓶颈：</strong> 最大的心魔是“我是不是不适合写代码”的自我怀疑。常常会遇到“瓶颈”，一个简单的 Bug 可能要耗费数日才能解决，此时急需一颗“筑基丹”（高人指点）方能突破。</li>
</ul>
</li>
</ul>
<h2>第二境：筑基期 &#8211; 合格的工程师</h2>
<p><img src="https://tonybai.com/wp-content/uploads/2025/fanren-xiuxian-programmer-levels-3.png" alt="" /><br />
<center>筑基期</center></p>
<p>经历无数次“走火入魔”后，终于炼化灵气，开辟丹田，成功“筑基”，体内的“灵力”（知识体系）凝聚成形。从此，你不再是修仙界的炮灰，而是一名真正的修士，可以独立执行任务，在宗门（团队）中有了一席之地。</p>
<ul>
<li><strong>境界特征：</strong>
<ul>
<li><strong>筑基成功，道途有望：</strong> 能够独立负责一个模块或一条业务线。对团队的技术栈了如指掌，是项目的中坚力量，道基稳固。</li>
<li><strong>拥有本命法器：</strong> 不再是见什么用什么，而是有了自己得心应手的“本命法器”（精通的框架或工具链），如 Spring 全家桶、Vue/React 生态。使用起来得心应手，威力倍增。</li>
<li><strong>神识初成，洞察秋毫：</strong> 开始具备一定的“神识”（Code Review 能力和设计嗅觉），能发现炼气期修士代码中的明显问题，并预见一些潜在的风险，如同神识外放，探查四周。</li>
<li><strong>独立执行宗门任务：</strong> 可以独立外出执行有一定难度的“宗门任务”（负责一个完整需求），并能顺利归来，不再需要师兄寸步不离地看护。</li>
</ul>
</li>
</ul>
<h2>第三境：结丹期 &#8211; 资深工程师 / 技术骨干</h2>
<p><img src="https://tonybai.com/wp-content/uploads/2025/fanren-xiuxian-programmer-levels-4.png" alt="" /><br />
<center>结丹期</center></p>
<p>此乃修行路上的巨大分水岭。修士将全身修为压缩、凝练，在丹田内结成一颗“金丹”（核心技术壁垒）。从此，寿元大增（职业生涯更稳定），神通广大，成为宗门里受人敬仰的长老级人物。</p>
<ul>
<li><strong>境界特征：</strong>
<ul>
<li><strong>凝结金丹，质的飞跃：</strong> 在某一领域（如高并发、分布式、数据库优化）形成了自己深厚的知识体系和方法论，这便是你的“金丹”。你是这个领域的 Go-to Person，是众人眼中可靠的“X哥”、“X姐”。</li>
<li><strong>本命法宝，威力大增：</strong> 不再满足于使用“法器”，开始炼制自己的“法宝”（轮子、工具库、脚手架），供宗门内弟子使用，极大提升了整个团队的战斗力。</li>
<li><strong>开辟洞府，传道授业：</strong> 开始承担起“长老”的职责，为宗门“开辟洞府”（搭建技术分享平台），“传道授业”（指导新人、进行技术培训），培养后辈力量，扩大自己的影响力。</li>
<li><strong>阵法大师，布局为先：</strong> 对小型系统的架构设计信手拈来，如同布置“阵法”，懂得权衡取舍，让系统在未来一段时间内稳固运行，易于扩展。</li>
</ul>
</li>
</ul>
<p><img src="https://tonybai.com/wp-content/uploads/course-card/iamtonybai-banner-2.gif" alt="" /></p>
<h2>第四境：元婴期 &#8211; 架构师 / 首席工程师</h2>
<p><img src="https://tonybai.com/wp-content/uploads/2025/fanren-xiuxian-programmer-levels-5.png" alt="" /><br />
<center>元婴期</center></p>
<p>碎丹成婴，道行进入全新天地。修士的“元婴”可以出窍，神游天外，对“天地法则”（系统规律）的理解远超常人。他们是宗门的守护神，轻易不出手，但一言一行都足以影响宗门的兴衰。</p>
<ul>
<li><strong>境界特征：</strong>
<ul>
<li><strong>元婴出窍，神游天外：</strong> 视角早已超越某个具体项目或业务线。他们的“元婴”（思想和影响力）可以“出窍”，俯瞰整个公司的技术体系，思考跨团队、跨领域的平台级问题。</li>
<li><strong>参悟天地法则：</strong> 深入理解分布式、高可用、可扩展性等“天地法则”。他们关注的不再是“术”（具体实现），而是“道”（设计哲学与原则），能在纷繁复杂的需求中，找到最核心的技术模型。</li>
<li><strong>开宗立派，影响一方：</strong> 他们设计的“护山大阵”（核心技术架构、平台），能支撑公司未来数年的发展。他们制定的“门规”（技术规范、研发流程），被众多弟子遵守，深刻影响着整个技术团队的文化和效率。</li>
<li><strong>趋吉避凶，未卜先知：</strong> 具备强大的技术预判能力，能洞察技术趋势，规避未来的技术债务和架构风险，带领宗门走在正确的“修行”道路上，避免误入歧途。</li>
</ul>
</li>
</ul>
<h2>第五境：化神期 &#8211; 技术大牛 / 领域开拓者</h2>
<p><img src="https://tonybai.com/wp-content/uploads/2025/fanren-xiuxian-programmer-levels-6.png" alt="" /><br />
<center>化神期</center></p>
<p>此境界已是人界的传说，神龙见首不见尾。他们对“道”的理解已返璞归真，能够洞悉本源，甚至创造规则。他们的存在，本身就是一座无法逾越的高山，是无数修士仰望的目标。</p>
<ul>
<li><strong>境界特征：</strong>
<ul>
<li><strong>返璞归真，大道至简：</strong> 他们的言论和代码往往看起来平平无奇，却蕴含着对技术最深刻的理解。能用最简单的语言解释最复杂的原理，如同“大道至简”，一言一行皆是道法自然。</li>
<li><strong>言出法随，创造规则：</strong> 他们不再是规则的遵守者，而是规则的创造者。他们创造的某个开源框架（如 K8s, TensorFlow）、某篇论文（如 MapReduce, DynamoDB），可能开创一个时代，成为无数修士修行的“根本大法”。</li>
<li><strong>破碎虚空，飞升上界：</strong> 他们的影响力早已超越一家公司，成为整个行业的灯塔。他们可能在顶级技术会议上“讲道”，也可能在某个开源社区中“点化”众生。对他们而言，换个公司已不是“跳槽”，而是“破碎虚空”，去往另一个更广阔的世界（灵界）。</li>
</ul>
</li>
</ul>
<h2>小结：路漫漫其修远兮</h2>
<p>修仙之路，道阻且长，行则将至。</p>
<p>从炼气期的迷茫，到筑基期的坚定；从结丹期的突破，到元婴期的洞察，乃至化神期的传说。每一个境界，都离不开日复一日的“打坐”（学习）、一次又一次的“渡劫”（攻克难题），以及那么一点点“机缘”（好的项目和团队以及赛道）。</p>
<p>韩立资质平平，却凭着“勤奋”与“谨慎”二字，终成大道。我辈程序员，或许没有逆天资质，但只要心向大道，勤勉不怠，终有一日，也能突破瓶颈，得见真我。</p>
<p>那么，各位道友，你现在修炼到哪个境界了？在修行路上又遇到了哪些瓶颈或趣事？欢迎在评论区留下你的“道号”和境界，我们一同论道！</p>
<hr />
<p><strong>想系统学习Go，构建扎实的知识体系？</strong></p>
<p>我的新书《<a href="https://book.douban.com/subject/37499496/">Go语言第一课</a>》是你的首选。源自2.4万人好评的极客时间专栏，内容全面升级，同步至Go 1.24。首发期有专属五折优惠，不到40元即可入手，扫码即可拥有这本300页的Go语言入门宝典，即刻开启你的Go语言高效学习之旅！</p>
<p><img src="https://tonybai.com/wp-content/uploads/2025/go-primer-published-4.png" alt="" /></p>
<hr />
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求，请扫描下方公众号二维码，与我私信联系。</p>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p style='text-align:left'>&copy; 2025, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2025/09/08/fanren-xiuxian-programmer-levels/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>致敬：程序员成长路上的良师与经典著作</title>
		<link>https://tonybai.com/2024/09/10/programmer-mentors-and-their-classic-works/</link>
		<comments>https://tonybai.com/2024/09/10/programmer-mentors-and-their-classic-works/#comments</comments>
		<pubDate>Tue, 10 Sep 2024 13:14:07 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[awk]]></category>
		<category><![CDATA[BjarneStroustrup]]></category>
		<category><![CDATA[BrianKernighan]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[C++Primer]]></category>
		<category><![CDATA[CodeCompleted]]></category>
		<category><![CDATA[Compiler]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[C程序设计语言]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[DennisRitchie]]></category>
		<category><![CDATA[DesignPatterns]]></category>
		<category><![CDATA[DonaldKnuth]]></category>
		<category><![CDATA[EffectiveCpp]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[gopl]]></category>
		<category><![CDATA[helloworld]]></category>
		<category><![CDATA[IP]]></category>
		<category><![CDATA[IPC]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JoshuaBloch]]></category>
		<category><![CDATA[KenThompson]]></category>
		<category><![CDATA[MIT]]></category>
		<category><![CDATA[OS]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[RobertSedgewick]]></category>
		<category><![CDATA[ScottMeyers]]></category>
		<category><![CDATA[SOLID]]></category>
		<category><![CDATA[TCP]]></category>
		<category><![CDATA[TheCProgrammingLanguage]]></category>
		<category><![CDATA[TheGoProgrammingLanguage]]></category>
		<category><![CDATA[ThinkingInCpp]]></category>
		<category><![CDATA[ThinkingInJava]]></category>
		<category><![CDATA[Unix]]></category>
		<category><![CDATA[WRichardStevens]]></category>
		<category><![CDATA[人月神话]]></category>
		<category><![CDATA[代码大全]]></category>
		<category><![CDATA[图灵奖]]></category>
		<category><![CDATA[套接字]]></category>
		<category><![CDATA[对象模型]]></category>
		<category><![CDATA[操作系统概念]]></category>
		<category><![CDATA[敏捷软件开发]]></category>
		<category><![CDATA[教师节]]></category>
		<category><![CDATA[数据库系统概念]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[算法]]></category>
		<category><![CDATA[算法导论]]></category>
		<category><![CDATA[编译原理]]></category>
		<category><![CDATA[编译器]]></category>
		<category><![CDATA[计算机]]></category>
		<category><![CDATA[计算机程序设计艺术]]></category>
		<category><![CDATA[设计模式]]></category>
		<category><![CDATA[谭浩强]]></category>
		<category><![CDATA[龙书]]></category>

		<guid isPermaLink="false">https://tonybai.com/?p=4273</guid>
		<description><![CDATA[本文永久链接 &#8211; https://tonybai.com/2024/09/10/programmer-mentors-and-their-classic-works 早上送孩子去幼儿园的路上，收到一个小伙伴的微信： 我这才意识到今天是教师节！为人师，自觉还不够格！但在这个特殊的日子，作为IT行业从业人员，我想向那些在计算机科学和编程领域给予我们启迪的“老师们”致敬。这些老师可能不是传统意义上站在讲台前的教育者，但他们通过自己的著作、思想和贡献，通过他们的智慧结晶，为我们指明了方向，为无数程序员的成长之路点亮了明灯。 这里我列举的作者与其著作也都是我个人从大学开始至今在计算机编程学习和实践之路上受到深刻影响的重要参考资料。这些书籍不仅丰富了我的知识，也激发了我对编程的热情和探索精神。每一位作者的独特视角和深入浅出的讲解，都让我在理解复杂概念时受益匪浅。希望也能引起大家的共鸣。 注：计算机领域巨匠甚多，笔者见识有限，不能一一列举，这里仅列出我亲自读过且对我影响深远的作者及其代表作品，至于像唐纳德·克努斯和他的巨著《计算机程序设计艺术》等，由于我并未拜读过，这里也就没有列出。 注：书中的图书封面图片可能并非该书最新版的封面，而是笔者购买时的版本的封面图片。 2. 编程语言 2.1 C语言/Go语言领域 2.1.1 Dennis Ritchie 大一的时候学校开设了C语言编程课，指定谭浩强老师的《C程序设计（第二版）》作为随课教材，当时我特意到大学书店花了银子买了本，并奉为皋臬。 直到我看到清华出版的影印版《C程序设计语言(第二版)》，才发现自己天真了，这本才是真正的“圣经”！ Dennis Ritchie，被誉为”C语言之父”，1983年图灵奖得主(与Ken Thompson同年获得)。他不仅创造了C语言，还与Ken Thompson一起开发了UNIX操作系统。刚刚过去的9月9日是其诞辰纪念日，MIT CSAIL在X上发文纪念了这位计算机先驱和现代编程语言奠基人： 他与Brian Kernighan合著的《The C Programming Language》被亲切地称为“K&#38;R C”，是学习C语言的必读经典，书籍不厚，它以简洁明了的语言介绍了C语言的核心概念(遵循当时的ANSI C89/C90标准)，影响了几代程序员。 2.1.2 Brian Kernighan 说完K&#38;R中的R，我们再来说K。K指的是Brian Kernighan，他也是Bell实验室UNIX开发团队的重要成员，是C语言的主要推广者之一，他也是AWK语言中的最后的那个K。和Dennis Ritchie等动不动就是语言之父不同，Kernighan以写作风格闻名。他的写作风格清晰易懂，使复杂的概念变得平易近人，并以一种易于理解和应用的方式呈现给读者。这使得与Dennis Ritchie合著的《C程序设计语言》不仅是C语言语言特性的权威指南，更是编程语言类书籍技术写作的典范，之后很多编程语言类的书籍都参考Kernighan的风格，至少也会先从一个“Hello, World”开始全书的讲解。 其与P.J.Plauger合著的《The Elements of Programming Style》也是程序员眼中的经典。 2015年，已经70高龄的Kernighan又和Go团队的Alan Donovan合著了Go语言编程书籍领域公认的圣经《The Go Programming Language》。这本书与K&#38;R C的风格很相似，作者们以清晰简洁的语言，系统且全面地介绍了Go的语法特性和编程理念，并通过大量的实例展示了Go在实际项目中的应用。书中不仅覆盖了基础知识，还深入探讨了并发编程、unsafe编程等Go高级主题。 2.2 C++ 2.2.1 Bjarne Stroustrup Bjarne Stroustrup是C++语言之父，他从1979年开始，在C语言的基础上添加了面向对象编程等特性，从而创造了C++这门强大而灵活的通用编程语言。C++经过ISO标准化后，他也是C++标准委员会的创始成员，并从那时起一直是一名活跃成员。如今，他还担任负责处理语言扩展提案的小组（进化工作组）的主席。 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-1.png" alt="" /></p>
<p><a href="https://tonybai.com/2024/09/10/programmer-mentors-and-their-classic-works">本文永久链接</a> &#8211; https://tonybai.com/2024/09/10/programmer-mentors-and-their-classic-works</p>
<p>早上送孩子去幼儿园的路上，收到一个小伙伴的微信：</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-2.png" alt="" /></p>
<p>我这才意识到今天是教师节！为人师，自觉还不够格！但在这个特殊的日子，作为IT行业从业人员，我想向那些在计算机科学和编程领域给予我们启迪的“老师们”致敬。这些老师可能不是传统意义上站在讲台前的教育者，但他们通过自己的著作、思想和贡献，通过他们的智慧结晶，为我们指明了方向，为无数程序员的成长之路点亮了明灯。</p>
<p>这里我列举的作者与其著作也都是我个人从大学开始至今在计算机编程学习和实践之路上受到深刻影响的重要参考资料。这些书籍不仅丰富了我的知识，也激发了我对编程的热情和探索精神。每一位作者的独特视角和深入浅出的讲解，都让我在理解复杂概念时受益匪浅。希望也能引起大家的共鸣。</p>
<blockquote>
<p>注：计算机领域巨匠甚多，笔者见识有限，不能一一列举，这里仅列出我亲自读过且对我影响深远的作者及其代表作品，至于像唐纳德·克努斯和他的巨著《<a href="https://book.douban.com/series/12331">计算机程序设计艺术</a>》等，由于我并未拜读过，这里也就没有列出。</p>
<p>注：书中的图书封面图片可能并非该书最新版的封面，而是笔者购买时的版本的封面图片。</p>
</blockquote>
<h2>2. 编程语言</h2>
<h3>2.1 C语言/Go语言领域</h3>
<h4>2.1.1 <a href="http://www.cs.bell-labs.com/~dmr">Dennis Ritchie</a></h4>
<p>大一的时候学校开设了C语言编程课，指定谭浩强老师的《<a href="https://book.douban.com/subject/1040868/">C程序设计（第二版）</a>》作为随课教材，当时我特意到大学书店花了银子买了本，并奉为皋臬。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-3.jpg" alt="" /></p>
<p>直到我看到清华出版的影印版《<a href="https://book.douban.com/subject/1230004/">C程序设计语言(第二版)</a>》，才发现自己天真了，这本才是真正的“圣经”！</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-4.png" alt="" /></p>
<p>Dennis Ritchie，被誉为”C语言之父”，1983年图灵奖得主(与Ken Thompson同年获得)。他不仅创造了C语言，还与Ken Thompson一起开发了UNIX操作系统。刚刚过去的9月9日是其诞辰纪念日，<a href="https://www.csail.mit.edu">MIT CSAIL</a>在X上发文纪念了这位计算机先驱和现代编程语言奠基人：</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-5.png" alt="" /></p>
<p>他与Brian Kernighan合著的《<a href="http://s3-us-west-2.amazonaws.com/belllabs-microsite-dritchie/cbook/index.html">The C Programming Language</a>》被亲切地称为“K&amp;R C”，是学习C语言的必读经典，书籍不厚，它以简洁明了的语言介绍了C语言的核心概念(遵循当时的ANSI C89/C90标准)，影响了几代程序员。</p>
<h4>2.1.2 <a href="https://www.cs.princeton.edu/~bwk/">Brian Kernighan</a></h4>
<p>说完K&amp;R中的R，我们再来说K。K指的是Brian Kernighan，他也是Bell实验室UNIX开发团队的重要成员，是C语言的主要推广者之一，他也是<a href="https://en.wikipedia.org/wiki/AWK">AWK语言</a>中的最后的那个K。和Dennis Ritchie等动不动就是语言之父不同，Kernighan以写作风格闻名。他的写作风格清晰易懂，使复杂的概念变得平易近人，并以一种易于理解和应用的方式呈现给读者。这使得与Dennis Ritchie合著的《C程序设计语言》不仅是C语言语言特性的权威指南，更是<strong>编程语言类书籍技术写作的典范</strong>，之后很多编程语言类的书籍都参考Kernighan的风格，至少也会先从一个“Hello, World”开始全书的讲解。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-7.jpeg" alt="" /></p>
<p>其与<a href="https://en.wikipedia.org/wiki/P._J._Plauger">P.J.Plauger</a>合著的《<a href="https://book.douban.com/subject/1470267/">The Elements of Programming Style</a>》也是程序员眼中的经典。</p>
<p>2015年，已经70高龄的Kernighan又和Go团队的Alan Donovan合著了Go语言编程书籍领域公认的圣经《<a href="https://www.gopl.io/">The Go Programming Language</a>》。这本书与K&amp;R C的风格很相似，作者们以清晰简洁的语言，系统且全面地介绍了Go的语法特性和编程理念，并通过大量的实例展示了Go在实际项目中的应用。书中不仅覆盖了基础知识，还深入探讨了并发编程、unsafe编程等Go高级主题。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-6.png" alt="" /></p>
<h3>2.2 C++</h3>
<h4>2.2.1 <a href="https://www.stroustrup.com/">Bjarne Stroustrup</a></h4>
<p>Bjarne Stroustrup是C++语言之父，他从1979年开始，在C语言的基础上添加了面向对象编程等特性，从而创造了C++这门强大而灵活的通用编程语言。C++经过ISO标准化后，他也是C++标准委员会的创始成员，并从那时起一直是一名活跃成员。如今，他还担任负责处理语言扩展提案的小组（进化工作组）的主席。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-8.jpeg" alt="" /></p>
<p>Bjarne Stroustrup的著作也是我入门和深入C++的必读经典，其中《C++程序设计语言》被认为是C++语言的”圣经”。Stroustrup以语言之父的口吻在书中详细介绍了C++的语言特性、抽象机制、标准库与设计理念。它不仅是一本语言参考，更是理解C++哲学的重要资源。</p>
<p>我是从高教影印版的《<a href="https://book.douban.com/subject/1231576/">The C++ Programming Language (Special Edition)</a>》开始看这本书的，与当时手里的钱能老师所著的《<a href="https://book.douban.com/subject/1041241/">C++程序设计教程</a>》相比，我感觉Stroustrup的The C++ Programming Language简直是在讲述一门新语言。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-9.jpg" alt="" /></p>
<p>Stroustrup的另外一本书《The Design and Evolution of C++》是C++进阶的必读之作，国内版译为《<a href="https://book.douban.com/subject/1096216/">C++语言的设计与演化</a>》，这本书可以理解为Stroustrup设计C++背后的心路历程以及设计决策与语言机制：</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-10.jpg" alt="" /></p>
<p>Stroustrup的书虽好，但读起来有些难度，对初学者可能不那么友好，尤其是The C++ Programming Language，更像是一本C++语言的spec，缺少了像Kernighan那种春风化雨的阅读体验，所以我个人更喜欢下面这位C++大佬的作品。</p>
<blockquote>
<p>注：Stroustrup这些年持续更新其作品，甚至还推出了《<a href="https://book.douban.com/subject/25720141/">A Tour of C++</a>》这样的更易读的小册子。</p>
</blockquote>
<h4>2.2.2 <a href="https://en.wikipedia.org/wiki/Stanley_B._Lippman">Stanley B. Lippman</a></h4>
<p>Stanley B. Lippman是Stroustrup的同事，早年和Stroustrup一起在Bell实验室开发C++编译器，2001年，Lippman加入微软，成为Visual C++的架构师。他最为人所称道的是他的“一厚一薄”两本C++经典著作。</p>
<p>我们先说这本厚的，它就是C++大部头：<a href="https://book.douban.com/subject/10505113/">《C++ Primer》</a>，这本书分为C++基础、C++标准库、类设计者的工具和高级主题四个部分，非常适合C++初学者，同样其高级主题对于有经验的C++熟手也有很高的价值。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-11.jpg" alt="" /></p>
<p>Lippman的另外一本薄书名为<a href="https://book.douban.com/subject/1484262/">《Inside the C++ Object Model》</a>，最初国内中译版《<a href="https://book.douban.com/subject/1091086/">深度探索C++对象模型</a>》由宝岛知名技术作家<a href="https://zh.wikipedia.org/zh-hans/%E4%BE%AF%E4%BF%8A%E5%82%91_(%E4%BD%9C%E5%AE%B6)">侯捷</a>翻译，如今的很多新一代程序员可能已经不知道侯捷老师了，他如今依然活跃在C++高级培训的舞台上。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-12.jpg" alt="" /></p>
<p>这本书属于C++进阶书籍，Lippman从C++编译器实现者的角度对C++的对象模型、继承和多态的实现机制(比如虚函数表、动态绑定等)等做了深入浅出的讲解，是C++走向高级阶段的必读之作。</p>
<p>不幸的是，Lippman已于2022年仙逝，我们再也看不到他亲自更新C++ Primer了。</p>
<h4>2.2.3 <a href="https://en.wikipedia.org/wiki/Scott_Meyers">Scott Meyers</a></h4>
<p>如果你学过C++，但没有看过Effective C++系列，那我可以肯定你不是C++高手，Scott Meyers的《Effective C++》系列书籍是C++程序员通往高手境界的必读书籍：</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-13.png" alt="" /></p>
<p>这套C++丛书的特色就是以一条条C++准则为单元，每一条都扼要说明了一个可让你写出更好的C++程序代码的方法，并以特别设计过的例子详加讨论，这非常适合程序员的胃口。</p>
<h3>2.3 Java</h3>
<p>我在工作初期<a href="https://tonybai.com/2004/10/10/java-basics/">曾经系统学过Java</a>，那时<a href="https://tonybai.com/2004/11/19/java5-research-part1/">Java刚刚发布5.0</a>，Spring也是方兴未艾。现在看来，没有Spring的Java是那么的纯粹！</p>
<p>学习纯Java，两本书足矣！下面我们就分别来看看这两本书和他们的作者。</p>
<h4>2.3.1 <a href="https://www.bruceeckel.com/">Bruce Eckel</a></h4>
<p>Bruce Eckel是著名的C++和Java作家，以其深入浅出的写作风格闻名。我没有将Eckel列到C++范畴，一是因为C++大神太多，二则是因为他的<a href="https://book.douban.com/subject/2130190/">Thinking in Java</a>似乎比他的<a href="https://book.douban.com/subject/1459728/">Thinking in C++</a>影响力更大。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-14.jpg" alt="" /></p>
<p>这本书《Java编程思想》被誉为学习Java最全面的资源之一。Eckel以其特有的方式，深入浅出地解释了Java的核心概念和高级特性。书中的例子丰富而实用，帮助读者真正理解和掌握Java编程，并这本书只讲纯Java语法，并不涉及任何框架。读过的朋友，还记得书中那句“Everything is an object”吗！</p>
<h4>2.3.2 <a href="https://en.wikipedia.org/wiki/Joshua_Bloch">Joshua Bloch</a></h4>
<p>和Bruce Eckel是一个作家和培训师不同，Joshua Bloch领导了许多Java平台功能的设计和实现，包括Java Collections Framework、java.math包和断言机制等，对Java语言和库的发展做出了重要贡献。他曾在Sun Microsystems担任杰出工程师。2004年他离开Sun，成为Google首席Java架构师。</p>
<p>和Bloch为Java实现做出的贡献相比，他的书籍在Java界更是“家喻户晓”，他曾自己或与其他人合著过多本Java书籍，包括Java Puzzlers、Java Concurrency In Practice以及Effective Java。而最后的《<a href="https://book.douban.com/subject/27047716/">Effective Java</a>》更是成为了Java程序员几乎人手一本的神作：</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-15.jpg" alt="" /></p>
<p>这本书提供了编写高质量Java代码的最佳实践。Bloch基于自己丰富的经验，提出了许多实用的建议，涵盖了从基本的编程习惯到高级主题如并发和序列化，其中每条建议都值得大家细致琢磨品味。这本书帮助无数Java程序员提升了代码质量和效率。</p>
<h2>3. 算法与数据结构</h2>
<p>程序员，永远绕不开算法与数据结构。在算法与数据结构领域，Donald E. Knuth无疑是祖师爷级别的，他写的多卷本大部头的“计算机程序设计艺术”被多少人买回后顶礼膜拜，却不曾拆封拜读:)。</p>
<p>更多人和我一样，喜欢更为实用的，能看懂的书籍资料。</p>
<h3>3.1 <a href="https://en.wikipedia.org/wiki/Robert_Sedgewick_(computer_scientist)">Robert Sedgewick</a></h3>
<p>首先我们来看Sedgewick和Wayne合著的作品：《<a href="https://book.douban.com/subject/19952400/">算法（第4版）</a>》。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-16.jpg" alt="" /></p>
<p>Robert Sedgewick是Donald E. Knuth的学生，名门之后，从1985年开始一直担任普林斯顿大学计算机科学系教授，曾任该系主任。很多耳熟能详的数据结构和算法都是Sedgewick发明的，比如红黑树、三元搜索树等。他基于课程讲义编写的这本“算法”，以清晰的讲解和丰富的Java实现而闻名。该书不仅介绍了经典数据结构和算法，还着重讨论了算法在实际问题中的应用。书中包含了大量的图示和代码，使得复杂的算法概念变得易于理解。这本书适合从入门到进阶的各个阶段的读者，是算法学习的必备参考。不过你不要想一下吃透这本书，很多算法非常深奥，可以将其作为案头的参考书，常看常新。</p>
<p>Sedgewick曾出版过多本算法书籍，有C实现的，有C++实现的，大家可以根据自己需要选择不同的实现版本。</p>
<h3>3.2 <a href="https://en.wikipedia.org/wiki/Thomas_H._Cormen">Thomas H. Cormen</a>和<a href="https://en.wikipedia.org/wiki/Charles_E._Leiserson">Charles E. Leiserson</a>等</h3>
<p>提到算法，就不能不提到另外一部大部头的经典著作《<a href="https://book.douban.com/subject/1152912/">算法导论</a>》</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-17.jpg" alt="" /></p>
<p>这部作品的英文版有上千页，可谓是算法领域的“百科全书”，这本书由 达特茅斯学院计算机科学系教授Thomas H. Cormen、麻省理工学院计算机科学与电气工程系教授Charles E. Leiserson等四人共同完成。这本书既全面又严谨，因此啃起来非常有难度，我在大学时期就买了该书的高教出版社的影印版，至今过去了十余年，我也没有完成全书的阅读:(。</p>
<p>在国内数据结构领域不得不说的另外一本教材是清华大学出版社出版的、由严蔚敏和吴伟民两位老师合著的《数据结构（C语言版）》，因很多高效将其作为考研指定教材，因此这本书的市占率很高，大家可以结合前面两个外版教材一起学习，效果可能更佳。下图是当年我购买时的版本样式：</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-18.png" alt="" /></p>
<h2>4. 软件工程与编程思想</h2>
<p>从大学毕业，入职工作后，软件工程知识必不可少，下面这些经典著作可以帮助大家快速融入工程领域。</p>
<h3>4.1 Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides</h3>
<p>这四位博士都是国际公认的面向对象软件领域的专家。他们在1994年合著的开创性的书籍<a href="https://book.douban.com/subject/1436745/">《设计模式：可复用面向对象软件的基础》</a>成为了开发人员在工程领域的必读之作，其影响力之广泛在整个IT领域都能排在TOP10。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-19.jpg" alt="" /></p>
<p>这本书定义并系统化了软件设计中的常见模式，为面向对象设计提供了一套通用词汇和最佳实践。书中详细描述了23种设计模式，并通过实例说明了它们的应用场景。这本书不仅影响了无数程序员的设计思想，也为软件工程领域提供了宝贵的参考。这四位博士的工作对软件设计模式的研究和应用产生了深远的影响。</p>
<h3>4.2 <a href="https://en.wikipedia.org/wiki/Steve_McConnell">Steve McConnell</a></h3>
<p>Steve McConnell是软件工程实践领域的权威专家，他的著作有不少，包括《Code Complete》、《Rapid Development 》和《Software Estimation》等，都对提高代码质量和开发效率有着重要影响。而其中影响力最大的莫过于《<a href="https://book.douban.com/subject/1477390/">代码大全（第2版）</a>》：</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-20.jpg" alt="" /></p>
<p>这是一本软件构建实践的百科全书，它涵盖了从变量命名到软件架构的各个方面。McConnell以丰富的经验和洞察力，提供了大量实用的编程技巧和最佳实践。这本书不仅适合新手学习，也是有经验的程序员提升技能的重要资源。并且，书中所讲的各种技巧和实践几乎与编程语言无关，无论你擅长哪种语言，都能从中获益！</p>
<h3>4.3 <a href="https://en.wikipedia.org/wiki/Robert_C._Martin">Robert C. Martin（Uncle Bob）</a></h3>
<p>Robert C. Martin，昵称”Uncle Bob”，是敏捷开发运动的重要推动者，也是软件工艺的倡导者。他的著作颇多，包括敏捷软件开发、敏捷整洁之道、代码整洁之道、匠艺整洁之道等。最近刚刚上市的《<a href="https://book.douban.com/subject/36974785/">函数式设计</a>》也出自Bob大叔之手。</p>
<p>在他的诸多作品中，《<a href="https://book.douban.com/subject/1140457/">敏捷软件开发：原则、模式与实践</a>》对我的影响更为深刻。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-21.jpg" alt="" /></p>
<p>在这本书中，Martin详细阐述了敏捷开发的核心原则(SOLID原则)，并通过大量的案例研究和设计模式，展示了如何在实践中应用这些原则。这本书不仅介绍了技术层面的最佳实践，还深入探讨了敏捷开发对团队协作和项目管理的影响。</p>
<h3>4.4 <a href="https://en.wikipedia.org/wiki/Andy_Hunt_(author)">Andrew Hunt</a>和<a href="https://en.wikipedia.org/wiki/Dave_Thomas_(programmer)">David Thomas</a></h3>
<p>Hunt和Thomas是两位经验丰富的软件开发者，他们的著作强调了持续学习和改进在程序员职业生涯中的重要性。他们共同开创了Pragmatic Programmer的概念，并通过其大作：《<a href="https://book.douban.com/subject/1152111/">程序员修炼之道：从小工到专家</a>》为开发人员讲述具体实践的方法：</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-22.jpg" alt="" /></p>
<p>这本书强调了在软件开发中保持务实态度的重要性。作者们通过一系列小贴士和练习，涵盖了从个人责任到知识投资等多个方面，帮助程序员不断提升自己的技能和职业素养。</p>
<h3>4.5 <a href="https://en.wikipedia.org/wiki/Fred_Brooks">Frederick P. Brooks Jr.</a></h3>
<p>谈到软件工程，我们不能忘记一个人，他就是Frederick P. Brooks Jr.。Brooks是一位美国计算机架构师、软件工程师和计算机科学家，以管理IBMSystem/360系列大型机和OS/360的开发而闻名。他在其开创性著作《<a href="https://book.douban.com/subject/1102259/">人月神话</a>》中坦率地写下了这些开发和项目管理经历，对后续的软件工程领域产生了深远的影响：</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-23.jpg" alt="" /></p>
<p>这本软件工程的经典之作挑战了许多关于软件开发的传统观念。Brooks通过自己在IBM的经历，深入探讨了大型软件项目管理中的各种问题。尽管首次出版已经过去多年，但书中关于团队沟通、项目规划和概念完整性等方面的见解至今仍然适用，是每个软件项目管理者入门必读的著作。</p>
<h2>5. 计算机系统</h2>
<p>最后，我们看一下计算机系统领域，我将系统编程、网络编程、编译器、数据库、操作系统统统放到这个领域一起说明了，排名不分先后:)。</p>
<h3>5.1 <a href="https://en.wikipedia.org/wiki/Randal_Bryant">Randal E.Bryant</a></h3>
<p>Randal Bryant是一位美国计算机科学家和学者，因其在形式验证数字硬件和软件方面的研究而闻名。Bryant自1984年以来一直在卡内基梅隆大学任教。2004年至2014年，他担任卡内基梅隆大学计算机科学学院(SCS)院长。他长期从事本科生和研究生计算机系统方面课程教学近40年。他和David O&#8217;Hallaron教授一起在卡内基梅隆大学开设了15-213课程“计算机系统导论”，其《<a href="https://book.douban.com/subject/26912767/">深入理解计算机系统</a>》便是以这门课的讲义为基础撰写而成的：</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-24.jpg" alt="" /></p>
<p>这本书涵盖了计算机系统的多个层面，包括硬件、操作系统、编程语言和网络等，使读者对计算机的整体架构有深入的理解。对于计算机专业入门的学生而言，这本书是必读的教材，国内尚没有类似的教材能望其项背！当年如果早早能看到这本教材该多好啊！</p>
<h3>5.2 <a href="http://www.kohala.com/start/">W. Richard Stevens</a></h3>
<p>Richard Stevens是UNIX和网络编程领域的权威专家，也是我顶礼膜拜的大神，他的著作对系统级编程产生了深远的影响。在我工作后的若干年内，Stevens的作品是我理解Unix/Linux系统编程的必备参考，并全部购买收藏，随时翻阅。更神奇的是，他的每一部作品都是上乘之作，看下面的豆瓣评分：</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-25.png" alt="" /></p>
<p>-《UNIX环境高级编程》</p>
<p>这本书被誉为UNIX编程的”圣经”。Stevens深入浅出地解释了UNIX系统调用和库函数的使用，涵盖了文件I/O、进程控制、信号处理、线程等关键主题。这本书不仅是学习UNIX/Linux系统编程的必备参考，也为理解操作系统内部工作原理提供了宝贵的见解。</p>
<p>-《UNIX网络编程》（卷1：套接字联网API，卷2：进程间通信）</p>
<p>相对于Unix环境高级编程的全面和总括，这套书深入具体领域，重点覆盖了UNIX环境下的网络编程和进程间通信技术。第一卷重点讲解了TCP/IP协议族和套接字编程，第二卷则专注于UNIX系统上的各种IPC（进程间通信）机制。这套书不仅提供了详细的技术讲解，还包含了大量的实例代码，是网络编程学习和实践的必备参考。</p>
<p>-《TCP/IP详解》系列</p>
<p>这套书深入浅出地解释了TCP/IP协议族的工作原理，从协议的基本概念到复杂的实现细节，为读者呈现了一幅完整的TCP/IP知识图谱。这套书不仅适合网络程序员阅读，也是理解现代互联网技术基础的重要资源。</p>
<p>对于Stevens的这些书，虽然年代已久，但对如今的后端/系统程序员依然有极大的参考价值，建议大家必读。</p>
<h3>5.3 <a href="https://en.wikipedia.org/wiki/Alfred_Aho">Alfred V. Aho</a>, Monica S. Lam, Ravi Sethi和Jeffrey D. Ullman</h3>
<p>以Alfred V. Aho为代表的这几位作者都是编译器理论和实现的权威专家，他们的著作被誉为编译原理领域的”圣经”。Alfred V. Aho同时也是AWK语言中的那个”A”，他还著有《<a href="https://book.douban.com/subject/2208525/">计算机算法的设计与分析</a>》。当然“龙书”是其在学术领域著作的最卓越代表，学编译原理的同学建议人手一本。</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-26.jpg" alt="" /></p>
<p>这本书以其全面性和深度在编译器领域独树一帜。从词法分析、语法分析到代码优化，书中详细讲解了编译器设计的各个环节。虽然以理论为主，但书中也包含了大量的实例和练习，帮助读者将理论付诸实践。这本书不仅是编译器开发者的必读之作，对理解程序语言的设计和实现也有重要帮助。国内各大开设编译原理课程的重点高校也都将其作为第一教材。国内一些高校也编写了一些自己的教材，但与这本“龙书”相比，level还是差距很大。</p>
<h3>5.4 <a href="https://en.wikipedia.org/wiki/Abraham_Silberschatz">Abraham Silberschatz</a></h3>
<p>Avi Silberschatz是一位以色列计算机科学家和研究员，曾在bell实验室工作过，他因在计算机科学领域撰写了许多有影响力的著作而闻名，尤其是操作系统和数据库系统方面。其作品<a href="https://book.douban.com/subject/35501216/">《数据库系统概念》</a>和<a href="https://book.douban.com/subject/30297919/">《操作系统概念》</a>被全世界的高校计算机专业所采用。</p>
<p>-《数据库系统概念》</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-27.jpg" alt="" /></p>
<p>本书由Abraham Silberschatz、 Henry F. Korth和S. Sudarshan合著，这三位作者都是数据库系统领域的专家，他们的著作被广泛用作大学教材和专业参考。这本书全面介绍了数据库系统的基本概念、设计原理和实现技术。从关系代数到事务处理，从查询优化到分布式数据库，书中涵盖了传统和现代数据库技术的各个方面。无论你是在校数据库专业的学生，还是从事数据库核心系统开发的工程师，亦或是数据库应用开发的程序员，本书都极具参考价值，可放置在案头随时查看。</p>
<p>-《操作系统概念》</p>
<p><img src="https://tonybai.com/wp-content/uploads/programmer-mentors-and-their-classic-works-28.jpg" alt="" /></p>
<p>本书由Abraham Silberschatz, Peter B. Galvin 和Greg Gagne合著，这几位作者都是操作系统理论和实践的专家，他们的著作在学术界和工业界都有广泛影响。</p>
<p>这本书以其全面性和深度成为了操作系统学习的重要参考。从进程管理到分布式系统，从内存管理到安全性，书中详细讨论了操作系统的各个方面。作者们不仅介绍了理论知识，还通过案例研究展示了这些概念在实际系统中的应用。这本书适合从入门到进阶的各个阶段的读者，是理解现代计算机操作系统工作原理的关键参考材料。</p>
<h2>6. 小结</h2>
<p>在教师节这个神圣的日子中，我们回顾了这些在计算机科学和编程领域做出杰出贡献的”老师们”。他们的智慧和洞见，通过这些经典著作，影响了几代程序员的成长，更是对我的程序员生涯提供了莫大的帮助。</p>
<p>这些大师们不仅仅传授了技术知识，更重要的是，他们塑造了我们思考问题和解决问题的方式。从C语言到Go，从算法到软件工程，从操作系统、编译原理到网络编程等，这些著作涵盖了计算机科学的方方面面，构建了现代软件开发的知识体系。</p>
<p>作为程序员，我们应该心怀感激，因为我们站在了这些巨人的肩膀上。同时，我们也要记住，学习是一个终身的过程。技术在不断进步，新的挑战不断出现，但这些经典著作中蕴含的智慧将永远指引我们前进的方向。</p>
<hr />
<p><a href="https://public.zsxq.com/groups/51284458844544">Gopher部落知识星球</a>在2024年将继续致力于打造一个高品质的Go语言学习和交流平台。我们将继续提供优质的Go技术文章首发和阅读体验。同时，我们也会加强代码质量和最佳实践的分享，包括如何编写简洁、可读、可测试的Go代码。此外，我们还会加强星友之间的交流和互动。欢迎大家踊跃提问，分享心得，讨论技术。我会在第一时间进行解答和交流。我衷心希望Gopher部落可以成为大家学习、进步、交流的港湾。让我相聚在Gopher部落，享受coding的快乐! 欢迎大家踊跃加入！</p>
<p><img src="http://image.tonybai.com/img/tonybai/gopher-tribe-zsxq-small-card.png" alt="img{512x368}" /><br />
<img src="http://image.tonybai.com/img/tonybai/go-programming-from-beginner-to-master-qr.png" alt="img{512x368}" /></p>
<p><img src="http://image.tonybai.com/img/tonybai/go-first-course-banner.png" alt="img{512x368}" /><br />
<img src="http://image.tonybai.com/img/tonybai/imooc-go-column-pgo-with-qr.jpg" alt="img{512x368}" /></p>
<p>著名云主机服务厂商DigitalOcean发布最新的主机计划，入门级Droplet配置升级为：1 core CPU、1G内存、25G高速SSD，价格5$/月。有使用DigitalOcean需求的朋友，可以打开这个<a href="https://m.do.co/c/bff6eed92687">链接地址</a>：https://m.do.co/c/bff6eed92687 开启你的DO主机之路。</p>
<p>Gopher Daily(Gopher每日新闻) &#8211; https://gopherdaily.tonybai.com</p>
<p>我的联系方式：</p>
<ul>
<li>微博(暂不可用)：https://weibo.com/bigwhite20xx</li>
<li>微博2：https://weibo.com/u/6484441286</li>
<li>博客：tonybai.com</li>
<li>github: https://github.com/bigwhite</li>
<li>Gopher Daily归档 &#8211; https://github.com/bigwhite/gopherdaily</li>
<li>Gopher Daily Feed订阅 &#8211; https://gopherdaily.tonybai.com/feed</li>
</ul>
<p><img src="http://image.tonybai.com/img/tonybai/iamtonybai-wechat-qr.png" alt="" /></p>
<p>商务合作方式：撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。</p>
<p style='text-align:left'>&copy; 2024, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2024/09/10/programmer-mentors-and-their-classic-works/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>探讨Docker容器中修改系统变量的方法</title>
		<link>https://tonybai.com/2014/10/14/discussion-on-the-approach-to-modify-system-variables-in-docker/</link>
		<comments>https://tonybai.com/2014/10/14/discussion-on-the-approach-to-modify-system-variables-in-docker/#comments</comments>
		<pubDate>Tue, 14 Oct 2014 13:56:12 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Blogger]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[init]]></category>
		<category><![CDATA[Kernel]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[phusion]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[Redhat]]></category>
		<category><![CDATA[SharedMemory]]></category>
		<category><![CDATA[shmget]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[共享内存]]></category>
		<category><![CDATA[内核]]></category>
		<category><![CDATA[博客]]></category>
		<category><![CDATA[容器]]></category>
		<category><![CDATA[工作]]></category>
		<category><![CDATA[开源]]></category>
		<category><![CDATA[思考]]></category>
		<category><![CDATA[感悟]]></category>
		<category><![CDATA[程序员]]></category>
		<category><![CDATA[虚拟化]]></category>

		<guid isPermaLink="false">http://tonybai.com/?p=1563</guid>
		<description><![CDATA[探讨完Docker对共享内存状态持久化的支持状况后，我将遗留产品build到一个pre-production image中，测试启动是否OK。很显然，我过于乐观了，Docker之路并不平坦。我收到了shmget报出的EINVAL错误码，提示参数非法。 shmget的manual对EINVAL错误码的说明如下： EINVAL： A&#160; new&#160; segment&#160; was&#160; to&#160; be&#160; created&#160; and size &#60; SHMMIN or size &#62; SHMMAX, or no new segment was to be created, a segment with given key existed, but size is greater than the size of that segment. 显然我们要创建的shared memory的size很可能大于SHMMAX这个系统变量了。那么一个从base image创建出的容器中的系统变量到底是什么值呢？我们来查看一下，我们基于&#34;centos:centos6&#34;启动一个Docker容器，并检查其中的 系统变量值设置： $ sudo docker run -it &#34;centos:centos6&#34; /bin/bash bash-4.1# [...]]]></description>
			<content:encoded><![CDATA[<p>探讨完<a href="http://tonybai.com/2014/10/12/discussion-on-shared-mem-support-in-docker/">Docker对共享内存状态持久化的支持状况</a>后，我将遗留产品build到一个pre-production image中，测试启动是否OK。很显然，我过于乐观了，<a href="http://www.docker.com">Docker</a>之路并不平坦。我收到了shmget报出的EINVAL错误码，提示参数非法。 shmget的manual对EINVAL错误码的说明如下：</p>
<p><font face="Courier New">EINVAL：<br />
	A&nbsp; new&nbsp; segment&nbsp; was&nbsp; to&nbsp; be&nbsp; created&nbsp; and size &lt; SHMMIN or size &gt; SHMMAX, or no new segment was to be created, a segment with given key existed, but size is greater than the size of that segment.</font></p>
<p>显然我们要创建的shared memory的size很可能大于SHMMAX这个系统变量了。那么一个从base image创建出的容器中的系统变量到底是什么值呢？我们来查看一下，我们基于&quot;centos:centos6&quot;启动一个Docker容器，并检查其中的 系统变量值设置：</p>
<p><font face="Courier New">$ sudo docker run -it &quot;centos:centos6&quot; /bin/bash<br />
	bash-4.1# cat /proc/sys/kernel/shmmax<br />
	33554432<br />
	bash-4.1# sysctl -a|grep shmmax<br />
	kernel.shmmax = 33554432</font></p>
<p>可以看出默认情况下，当前容器中root账号看到的shmmax值我<font face="Courier New">33554432</font>， 我的程序要创建的shm size的确要大于这个值，报出EINVAL错误也就无可厚非了。我尝试按照物理机上的方法临时修改一下该值：</p>
<p><font face="Courier New">bash-4.1# echo 68719476736 &gt; /proc/sys/kernel/shmmax<br />
	bash: /proc/sys/kernel/shmmax: Read-only file system</font></p>
<p><font face="Courier New">/proc/sys/kernel/shmmax居然是只读的，无法修改。</font></p>
<p><font face="Courier New">我又尝试修改/etc/sysctl.conf这个持久化系统变量的地方，但打开/etc/sysctl.conf文件，我发现我又错了，这 个文件中shmmax的值如下：</font></p>
<p><font face="Courier New"># Controls the maximum shared segment size, in bytes<br />
	kernel.shmmax = 68719476736</font></p>
<p><font face="Courier New"><font face="Courier New">/etc/sysctl.conf文件 中的系统变量shmmax的值是68719476736，而系统当前的实际值则是33554432，难道是/etc /sysctl.conf中的值没有生效，于是我手工重新加载一次该文件：</font></font></p>
<p><font face="Courier New"><font face="Courier New">-bash-4.1# sysctl -p<br />
	error: &quot;Read-only file system&quot; setting key &quot;net.ipv4.ip_forward&quot;<br />
	error: &quot;Read-only file system&quot; setting key &quot;net.ipv4.conf.default.rp_filter&quot;<br />
	error: &quot;Read-only file system&quot; setting key &quot;net.ipv4.conf.default.accept_source_route&quot;<br />
	error: &quot;Read-only file system&quot; setting key &quot;kernel.sysrq&quot;<br />
	error: &quot;Read-only file system&quot; setting key &quot;kernel.core_uses_pid&quot;<br />
	error: &quot;net.ipv4.tcp_syncookies&quot; is an unknown key<br />
	error: &quot;net.bridge.bridge-nf-call-ip6tables&quot; is an unknown key<br />
	error: &quot;net.bridge.bridge-nf-call-iptables&quot; is an unknown key<br />
	error: &quot;net.bridge.bridge-nf-call-arptables&quot; is an unknown key<br />
	error: &quot;Read-only file system&quot; setting key &quot;kernel.msgmnb&quot;<br />
	error: &quot;Read-only file system&quot; setting key &quot;kernel.msgmax&quot;<br />
	error: &quot;Read-only file system&quot; setting key &quot;kernel.shmmax&quot;<br />
	error: &quot;Read-only file system&quot; setting key &quot;kernel.shmall&quot;</font></font></p>
<p><font face="Courier New"><font face="Courier New">我得到了和之前类似的错误结果：只读文件系统，无法修改。于是乎两个问题萦绕在我的面前：<br />
	1、为什么容器内当前系统变量值与sysctl.conf中的不一致？<br />
	2、为什么无法修改当前系统变量值?</font></font></p>
<p><font face="Courier New"><font face="Courier New">在翻阅了Stackoverflow, github docker issues后，我得到了的答案如下：</font></font></p>
<p><font face="Courier New"><font face="Courier New">1、Docker的base image做的很精简，甚至都没有init进程，原本在OS启动时执行生效系统变量的过程(sysctl -p)也给省略了，导致这些系统变量依旧保留着kernel默认值。以CentOs为例，在linux kernel boot后，init都会执行/etc/rc.d/rc.sysinit，后者会加载/etc/sysctl.conf中的系统变量值。下面是 CentOs5.6中的rc.sysinit代码摘录：</font></font></p>
<p><font face="Courier New"><font face="Courier New">&#8230; &#8230;<br />
	# Configure kernel parameters<br />
	update_boot_stage RCkernelparam<br />
	sysctl -e -p /etc/sysctl.conf &gt;/dev/null 2&gt;&amp;1<br />
	&#8230; &#8230;</font></font></p>
<p><font face="Courier New"><font face="Courier New">2、Docker容器中的系统变量在non-priviledged模式下目前(我使用的时docker 1.2.0版本)就无法修改，</font></font>这 和resolv.conf、hosts等文件映射到宿主机对应的文件有不同。</p>
<p><font face="Courier New">$ mount -l<br />
	&#8230;. &#8230;.<br />
	/dev/mapper/ubuntu&#8211;Server&#8211;14&#8211;vg-root on /etc/resolv.conf type ext4 (rw,relatime,errors=remount-ro,data=ordered)<br />
	/dev/mapper/ubuntu&#8211;Server&#8211;14&#8211;vg-root on /etc/hostname type ext4 (rw,relatime,errors=remount-ro,data=ordered)<br />
	/dev/mapper/ubuntu&#8211;Server&#8211;14&#8211;vg-root on /etc/hosts type ext4 (rw,relatime,errors=remount-ro,data=ordered)<br />
	&#8230; &#8230;</font></p>
<p>那么我们该如何修改系统变量值来满足遗留产品的需求呢？</p>
<p><b>一、使用&#8211;privileged选项</b></p>
<p>我们使用&#8211;privileged这个特权选项来启动一个基于centos:centos6的新容器，看看是否能对shmmax这样的系统变量值 进行修改：</p>
<p><font face="Courier New">$ sudo docker run -it &#8211;privileged&nbsp; &quot;centos:centos6&quot; /bin/bash<br />
	bash-4.1# cat /proc/sys/kernel/shmmax<br />
	33554432<br />
	bash-4.1# echo 68719476736 &gt; /proc/sys/kernel/shmmax<br />
	bash-4.1# cat /proc/sys/kernel/shmmax<br />
	68719476736</font><br />
	<font face="Courier New">bash-4.1# sysctl -p<br />
	net.ipv4.ip_forward = 0<br />
	net.ipv4.conf.default.rp_filter = 1<br />
	net.ipv4.conf.default.accept_source_route = 0<br />
	kernel.sysrq = 0<br />
	kernel.core_uses_pid = 1<br />
	&#8230; &#8230;<br />
	kernel.msgmnb = 65536<br />
	kernel.msgmax = 65536<br />
	kernel.shmmax = 68719476736<br />
	kernel.shmall = 4294967296</font></p>
<p>可以看出，通过&#8211;privileged选项，容器获得了额外的特权，并且可以对系统变量的值进行修改了。不过这样的修改是不能保存在容器里的， 我们stop 容器，再重启该容器就能看出来：</p>
<p><font face="Courier New">$ sudo docker start 3e22d65a7845<br />
	$ sudo docker attach 3e22d65a7845<br />
	bash-4.1# cat /proc/sys/kernel/shmmax<br />
	33554432</font></p>
<p>shmmax的值在容器重启后又变回了原先的那个默认值。不过重启后的容器依旧具有privileged的特权，我们还可以重新手工执行命令对系 统变量进行修改：</p>
<p><font face="Courier New">bash-4.1# echo 68719476736 &gt; /proc/sys/kernel/shmmax<br />
	bash-4.1# cat /proc/sys/kernel/shmmax<br />
	68719476736</font></p>
<p>但即便这样，也无法满足我们的需求，我们总不能每次都在容器中手工执行系统变量值修改的操作吧。privileged选项的能力能否带到 image中呢？答案是目前还不能，我们无法在build image时通过privileged选项修改系统变量值。</p>
<p>这样一来，我们能做的只有把产品启动与系统变量值修改放在一个脚本中了，并将该脚本作为docker 容器的cmd命令来执行，比如我们构建一个Dockerfile：</p>
<p><font face="Courier New">FROM centos:centos6<br />
	MAINTAINER Tony Bai <a class="moz-txt-link-rfc2396E" href="mailto:bigwhite.cn@gmail.com">&lt;bigwhite.cn@gmail.com&gt;</a><br />
	RUN yum install python-setuptools -y<br />
	RUN easy_install supervisor<br />
	RUN mkdir -p /var/log/supervisor<br />
	COPY ./supervisord.conf /etc/supervisord.conf<br />
	COPY ./start.sh /bin/start.sh<br />
	RUN chmod +x /bin/start.sh<br />
	CMD ["/bin/start.sh]</font></p>
<p><font face="Courier New">//start.sh<br />
	sysctl -p<br />
	/usr/bin/supervisord</font></p>
<p>这样，start.sh在supervisord启动前将系统变量值重新加载，而supervisord后续启动的程序就可以看到这些新系统变量 的值了。不过别忘了利用这个image启动容器时要加上&#8211;priviledged选项，否则容器启动就会失败。</p>
<p><b>二、使用phusion/baseimage</b></p>
<p>前面说过/etc/sysctl.conf中的值没有生效是因为docker官方提供的centos:centos6把init进程的初始化过程给精 简掉了。<a href="https://registry.hub.docker.com/u/phusion/baseimage/">phusion/baseimage</a>是目前docker registery上仅次于ubuntu和centos两个之后的base image，其提供了/sbin/my_init这个init进程，用于在container充当init进程的角色。那么my_init是否可以用于执行sysctl -p呢？我们试验一下：</p>
<p>我们先pull这个base image下来：<font face="Courier New">sudo docker pull phusion/baseimage。pull成功后，我们先基于&ldquo;phusion/baseimage&rdquo;启动一个容器做一些explore工作：</font></p>
<p><font face="Courier New">$ sudo docker run -i -t &quot;phusion/baseimage&quot;<br />
	*** Running /etc/my_init.d/00_regen_ssh_host_keys.sh&#8230;<br />
	No SSH host key available. Generating one&#8230;<br />
	Creating SSH2 RSA key; this may take some time &#8230;<br />
	Creating SSH2 DSA key; this may take some time &#8230;<br />
	Creating SSH2 ECDSA key; this may take some time &#8230;<br />
	Creating SSH2 ED25519 key; this may take some time &#8230;<br />
	invoke-rc.d: policy-rc.d denied execution of restart.<br />
	*** Running /etc/rc.local&#8230;<br />
	*** Booting runit daemon&#8230;<br />
	*** Runit started as PID 100</font></p>
<p><font face="Courier New">通过nsenter进去，查看一下/sbin/my_init的源码，我们发现这是一个python脚本，不过从头到尾浏览一遍，没有发现sysctl加载/etc/sysctl.conf系统变量的操作。</font></p>
<p><font face="Courier New">不过，phusion文档中说my_init可以在初始化过程中执行/etc/my_init.d下的脚本。那是不是我们将一个执行sysctl -p的脚本放入/etc/my_init.d下就可以实现我们的目的了呢？试试。</font></p>
<p><font face="Courier New">我们编写一个脚本：load_sys_varibles.sh</font></p>
<p><font face="Courier New">#!/bin/sh<br />
	sysctl -p &gt; init.txt</font></p>
<p><font face="Courier New">下面是制作image的Dockerfile:</font></p>
<p><font face="Courier New">FROM phusion/baseimage:latest<br />
	MAINTAINER Tony Bai &lt;bigwhite.cn@gmail.com&gt;<br />
	RUN echo &quot;kernel.shmmax = 68719476736&quot; &gt;&gt; /etc/sysctl.conf<br />
	RUN mkdir -p /etc/my_init.d<br />
	ADD load_sys_varibles.sh /etc/my_init.d/load_sys_varibles.sh<br />
	RUN chmod +x /etc/my_init.d/load_sys_varibles.sh<br />
	CMD ["/sbin/my_init"]</font></p>
<p><font face="Courier New">phusion/baseimage是基于ubuntu的OS，其sysctl.conf默认情况下没啥内容，所以我们在Dockerfile中向这个文件写入我们需要的系统变量值。构建image并启动容器：</font></p>
<p><font face="Courier New">$ sudo docker build -t &quot;myphusion:v1&quot; ./<br />
	Sending build context to Docker daemon 13.12 MB<br />
	Sending build context to Docker daemon<br />
	Step 0 : FROM phusion/baseimage:latest<br />
	&nbsp;&#8212;&gt; cf39b476aeec<br />
	Step 1 : MAINTAINER Tony Bai &lt;bigwhite.cn@gmail.com&gt;<br />
	&nbsp;&#8212;&gt; Using cache<br />
	&nbsp;&#8212;&gt; d0e9b51a3e4f<br />
	Step 2 : RUN echo &quot;kernel.shmmax = 68719476736&quot; &gt;&gt; /etc/sysctl.conf<br />
	&nbsp;&#8212;&gt; Using cache<br />
	&nbsp;&#8212;&gt; 2c800687cc83<br />
	Step 3 : RUN mkdir -p /etc/my_init.d<br />
	&nbsp;&#8212;&gt; Using cache<br />
	&nbsp;&#8212;&gt; fe366eea5eb4<br />
	Step 4 : ADD load_sys_varibles.sh /etc/my_init.d/load_sys_varibles.sh<br />
	&nbsp;&#8212;&gt; a641bb595fb9<br />
	Removing intermediate container c381b9f001c2<br />
	Step 5 : RUN chmod +x /etc/my_init.d/load_sys_varibles.sh<br />
	&nbsp;&#8212;&gt; Running in 764866552f25<br />
	&nbsp;&#8212;&gt; eae3d7f1eac5<br />
	Removing intermediate container 764866552f25<br />
	Step 6 : CMD ["/sbin/my_init"]<br />
	&nbsp;&#8212;&gt; Running in 9ab8d0b717a7<br />
	&nbsp;&#8212;&gt; 8be4e7b6b174<br />
	Removing intermediate container 9ab8d0b717a7<br />
	Successfully built 8be4e7b6b174</font></p>
<p><font face="Courier New">$ sudo docker run -it &quot;myphusion:v1&quot;<br />
	*** Running /etc/my_init.d/00_regen_ssh_host_keys.sh&#8230;<br />
	No SSH host key available. Generating one&#8230;<br />
	Creating SSH2 RSA key; this may take some time &#8230;<br />
	Creating SSH2 DSA key; this may take some time &#8230;<br />
	Creating SSH2 ECDSA key; this may take some time &#8230;<br />
	Creating SSH2 ED25519 key; this may take some time &#8230;<br />
	invoke-rc.d: policy-rc.d denied execution of restart.<br />
	*** Running /etc/my_init.d/load_sys_varibles.sh&#8230;<br />
	sysctl: setting key &quot;kernel.shmmax&quot;: Read-only file system<br />
	*** /etc/my_init.d/load_sys_varibles.sh failed with status 255</font></p>
<p><font face="Courier New">*** Killing all processes&#8230;</font></p>
<p><font face="Courier New">唉，还是老问题！即便是在my_init中执行，依旧无法逾越Read-only file system，查看Phusion/baseimage的Dockerfile才知道，它也是From ubuntu:14.04的，根不变，上层再怎么折腾也没用。</font></p>
<p><font face="Courier New">换一种容器run方法吧，加上&#8211;privileged：</font></p>
<p><font face="Courier New">$ sudo docker run -it &#8211;privileged&nbsp; &quot;myphusion:v1&quot;<br />
	*** Running /etc/my_init.d/00_regen_ssh_host_keys.sh&#8230;<br />
	No SSH host key available. Generating one&#8230;<br />
	Creating SSH2 RSA key; this may take some time &#8230;<br />
	Creating SSH2 DSA key; this may take some time &#8230;<br />
	Creating SSH2 ECDSA key; this may take some time &#8230;<br />
	Creating SSH2 ED25519 key; this may take some time &#8230;<br />
	invoke-rc.d: policy-rc.d denied execution of restart.<br />
	*** Running /etc/my_init.d/load_sys_varibles.sh&#8230;<br />
	*** Running /etc/rc.local&#8230;<br />
	*** Booting runit daemon&#8230;<br />
	*** Runit started as PID 102</font></p>
<p><font face="Courier New">这回灵光了。enter到容器里看看设置的值是否生效了：</font></p>
<p><font face="Courier New">root@9e399f46372a:~#cat /proc/sys/kernel/shmmax<br />
	68719476736</font></p>
<p><font face="Courier New">结果如预期。这样来看phusion/baseimage算是为sysctl -p加载系统变量值提供了一个便利，但依旧无法脱离&#8211;privileged，且依旧无法在image中持久化这个设置。</font></p>
<p><font face="Courier New">在Docker github的issue中有人提出建议在Dockerfile中加入类似RUNP这样的带有特权的指令语法，但不知何时才能在Docker中加入这一功能。</font></p>
<p><font face="Courier New">总而言之，基于目前docker官网提供的base image，我们很难找到特别理想的修改系统变量值的方法，除非自己制作base image，这个还没尝试过，待后续继续研究。</font></p>
<p style='text-align:left'>&copy; 2014, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2014/10/14/discussion-on-the-approach-to-modify-system-variables-in-docker/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>探讨docker容器对共享内存的支持情况</title>
		<link>https://tonybai.com/2014/10/12/discussion-on-shared-mem-support-in-docker/</link>
		<comments>https://tonybai.com/2014/10/12/discussion-on-shared-mem-support-in-docker/#comments</comments>
		<pubDate>Sat, 11 Oct 2014 21:23:34 +0000</pubDate>
		<dc:creator>bigwhite</dc:creator>
				<category><![CDATA[技术志]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Blogger]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[Golang]]></category>
		<category><![CDATA[IPC]]></category>
		<category><![CDATA[Kernel]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[mmap]]></category>
		<category><![CDATA[POSIX]]></category>
		<category><![CDATA[Programmer]]></category>
		<category><![CDATA[SharedMemory]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[共享内存]]></category>
		<category><![CDATA[内核]]></category>
		<category><![CDATA[容器]]></category>
		<category><![CDATA[工作]]></category>
		<category><![CDATA[思考]]></category>
		<category><![CDATA[程序员]]></category>

		<guid isPermaLink="false">http://tonybai.com/?p=1560</guid>
		<description><![CDATA[我们的遗留系统广泛使用了性能最佳的IPC方式 &#8211; 共享内存，而且用到了两种共享内存的实现方式：System V共享内存(shmget、shmat、shmdt)以及Mmap映射Regular File。System V共享内存支持一定程度上的内存数据持久化，即当程序创建共享内存对象后，如果不显式删除或物理主机重启，该IPC对象会一直保留，其中的数据也不会丢 失；mmap映射Regular File的方式支持内存数据持久化到文件中，即便物理主机重启，这部分数据依旧不会丢失，除非显式删除文件。这两个共享内存机制，尤其是其持久化的特性是 我们的系统所依赖的。但是在Docker容器中，这两种共享内存机制依旧能被很好的支持吗？我们通过试验来分析一下。 一、System V共享内存 一个启动的Docker容器就是一个拥有了自己的内核名字空间的进程，其pid、net、ipc、mnt、uts、user等均与其他进程隔离，对于运行于该容器内的程序而言，它仿佛会觉得它独占了一台&#8220;主机&#8221;。对于这类&#8220;主机&#8221;，我们首先来测试一下其中的system v共享内存是否依旧能像物理主机上一样，在程序退出后依旧能保持持久化？在容器退出后能保持么？ 我们先来写两个测试程序，一个用于创建system v共享内存，并写入一些数据，另外一个程序则映射该共享内存并尝试读出内存中的数据。由于Golang目前仍未提供对System V共享内存的高级封装接口，通过syscall包的Syscall调用又太繁琐，因此我们直接使用C代码与Go代码结合的方式实现这两个测试程序。之前写 过一篇名为《Go与C语言互操作》的博文，看不懂下面代码的朋友，可以先阅读一下这篇文章。 //systemv_shm_wr.go package main //#include &#60;sys/types.h&#62; //#include &#60;sys/ipc.h&#62; //#include &#60;sys/shm.h&#62; //#include &#60;stdio.h&#62; // //#define SHMSZ&#160;&#160;&#160;&#160; 27 // //int shm_wr() { //&#160;&#160;&#160; char c; //&#160;&#160;&#160; int shmid; //&#160;&#160;&#160; key_t key; //&#160;&#160;&#160; char *shm, *s; // //&#160;&#160;&#160; key = 5678; // [...]]]></description>
			<content:encoded><![CDATA[<p>我们的遗留系统广泛使用了性能最佳的IPC方式 &#8211; <a href="http://en.wikipedia.org/wiki/Shared_memory">共享内存</a>，而且用到了两种共享内存的实现方式：System V共享内存(shmget、shmat、shmdt)以及Mmap映射Regular File。System V共享内存支持一定程度上的内存数据持久化，即当程序创建共享内存对象后，如果不显式删除或物理主机重启，该IPC对象会一直保留，其中的数据也不会丢 失；mmap映射Regular File的方式支持内存数据持久化到文件中，即便物理主机重启，这部分数据依旧不会丢失，除非显式删除文件。这两个共享内存机制，尤其是其持久化的特性是 我们的系统所依赖的。但是在<a href="http://docker.com">Docker</a>容器中，这两种共享内存机制依旧能被很好的支持吗？我们通过试验来分析一下。</p>
<p><b>一、System V共享内存</b></p>
<p>一个启动的Docker容器就是一个拥有了自己的内核名字空间的进程，其<b>pid</b><b>、net</b><b>、ipc</b><b>、mnt</b><b>、uts</b><b>、user</b>等均与其他进程隔离，对于运行于该容器内的程序而言，它仿佛会觉得它独占了一台&ldquo;主机&rdquo;。对于这类&ldquo;主机&rdquo;，我们首先来测试一下其中的system v共享内存是否依旧能像物理主机上一样，在程序退出后依旧能保持持久化？在容器退出后能保持么？</p>
<p>我们先来写两个测试程序，一个用于创建system v共享内存，并写入一些数据，另外一个程序则映射该共享内存并尝试读出内存中的数据。由于Golang目前仍未提供对System V共享内存的高级封装接口，通过syscall包的Syscall调用又太繁琐，因此我们直接使用C代码与Go代码结合的方式实现这两个测试程序。之前写 过一篇名为《<a href="http://tonybai.com/2012/09/26/interoperability-between-go-and-c/">Go与C语言互操作</a>》的博文，看不懂下面代码的朋友，可以先阅读一下这篇文章。</p>
<p><font face="Courier New">//systemv_shm_wr.go<br />
	package main</font></p>
<p><font face="Courier New">//#include &lt;sys/types.h&gt;<br />
	//#include &lt;sys/ipc.h&gt;<br />
	//#include &lt;sys/shm.h&gt;<br />
	//#include &lt;stdio.h&gt;<br />
	//<br />
	//#define SHMSZ&nbsp;&nbsp;&nbsp;&nbsp; 27<br />
	//<br />
	//int shm_wr() {<br />
	//&nbsp;&nbsp;&nbsp; char c;<br />
	//&nbsp;&nbsp;&nbsp; int shmid;<br />
	//&nbsp;&nbsp;&nbsp; key_t key;<br />
	//&nbsp;&nbsp;&nbsp; char *shm, *s;<br />
	//<br />
	//&nbsp;&nbsp;&nbsp; key = 5678;<br />
	//<br />
	//&nbsp;&nbsp;&nbsp; if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) &lt; 0) {<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />
	//&nbsp;&nbsp;&nbsp; }<br />
	//<br />
	//&nbsp;&nbsp;&nbsp; if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -2;<br />
	//&nbsp;&nbsp;&nbsp; }<br />
	//<br />
	//&nbsp;&nbsp;&nbsp; s = shm;<br />
	//&nbsp;&nbsp;&nbsp; for (c = &#39;a&#39;; c &lt;= &#39;z&#39;; c++)<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *s++ = c;<br />
	//&nbsp;&nbsp;&nbsp; s = NULL;<br />
	//<br />
	//&nbsp;&nbsp;&nbsp; return 0;<br />
	//}<br />
	import &quot;C&quot;</font></p>
<p><font face="Courier New">import &quot;fmt&quot;</font></p>
<p><font face="Courier New">func main() {<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i := C.shm_wr()<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if i != 0 {<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fmt.Println(&quot;SystemV Share Memory Create and Write Error:&quot;, i)<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fmt.Println(&quot;SystemV Share Memory Create and Write Ok&quot;)<br />
	}</font></p>
<p><font face="Courier New">//systemv_shm_rd.go</font></p>
<p><font face="Courier New">package main</font></p>
<p><font face="Courier New">//#include &lt;sys/types.h&gt;<br />
	//#include &lt;sys/ipc.h&gt;<br />
	//#include &lt;sys/shm.h&gt;<br />
	//#include &lt;stdio.h&gt;<br />
	//<br />
	//#define SHMSZ&nbsp;&nbsp;&nbsp;&nbsp; 27<br />
	//<br />
	//int shm_rd() {<br />
	//&nbsp;&nbsp;&nbsp; char c;<br />
	//&nbsp;&nbsp;&nbsp; int shmid;<br />
	//&nbsp;&nbsp;&nbsp; key_t key;<br />
	//&nbsp;&nbsp;&nbsp; char *shm, *s;<br />
	//<br />
	//&nbsp;&nbsp;&nbsp; key = 5678;<br />
	//<br />
	//&nbsp;&nbsp;&nbsp; if ((shmid = shmget(key, SHMSZ, 0666)) &lt; 0) {<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />
	//&nbsp;&nbsp;&nbsp; }<br />
	//<br />
	//&nbsp;&nbsp;&nbsp; if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -2;<br />
	//&nbsp;&nbsp;&nbsp; }<br />
	//<br />
	//&nbsp;&nbsp;&nbsp; s = shm;<br />
	//<br />
	//&nbsp;&nbsp;&nbsp; int i = 0;<br />
	//&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; SHMSZ-1; i++)<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&quot;%c &quot;, *(s+i));<br />
	//&nbsp;&nbsp;&nbsp; printf(&quot;\n&quot;);<br />
	//&nbsp;&nbsp;&nbsp; s = NULL;<br />
	//<br />
	//&nbsp;&nbsp;&nbsp; return 0;<br />
	//}<br />
	import &quot;C&quot;</font></p>
<p><font face="Courier New">import &quot;fmt&quot;</font></p>
<p><font face="Courier New">import &quot;fmt&quot;</font></p>
<p><font face="Courier New">func main() {<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i := C.shm_rd()<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if i != 0 {<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fmt.Println(&quot;SystemV Share Memory Create and Read Error:&quot;, i)<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fmt.Println(&quot;SystemV Share Memory Create and Read Ok&quot;)<br />
	}</font></p>
<p>我们通过go build构建上面两个程序，得到两个测试用可执行程序：systemv_shm_wr和systemv_shm_rd。下面我们来构建我们的测试用docker image，Dockerfile内容如下：</p>
<p><font face="Courier New">FROM centos:centos6<br />
	MAINTAINER Tony Bai &lt;bigwhite.cn@gmail.com&gt;<br />
	COPY ./systemv_shm_wr /bin/<br />
	COPY ./systemv_shm_rd /bin/</font></p>
<p>构建Docker image：&ldquo;shmemtest:v1&rdquo;：</p>
<p><font face="Courier New">$ sudo docker build -t=&quot;shmemtest:v1&quot; ./<br />
	Sending build context to Docker daemon 16.81 MB<br />
	Sending build context to Docker daemon<br />
	Step 0 : FROM centos:centos6<br />
	&nbsp;&#8212;&gt; 68edf809afe7<br />
	Step 1 : MAINTAINER Tony Bai &lt;bigwhite.cn@gmail.com&gt;<br />
	&nbsp;&#8212;&gt; Using cache<br />
	&nbsp;&#8212;&gt; c617b456934a<br />
	Step 2 : COPY ./systemv_shm_wr /bin/<br />
	&nbsp;&#8212;&gt; ea59fb767573<br />
	Removing intermediate container 4ce91720897b<br />
	Step 3 : COPY ./systemv_shm_rd /bin/<br />
	&nbsp;&#8212;&gt; 1ceb207b1009<br />
	Removing intermediate container 7ace7ad53a3f<br />
	Successfully built 1ceb207b1009</font></p>
<p>启动一个基于该image的容器：<br />
	<font face="Courier New">$ sudo docker run -it &quot;shmemtest:v1&quot; /bin/bash</font></p>
<p><font face="Courier New">$ sudo docker ps<br />
	CONTAINER ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IMAGE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COMMAND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CREATED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STATUS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NAMES<br />
	0a2f37bee6eb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shmemtest:v1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;/bin/bash&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 28 seconds ago&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Up 28 seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elegant_hawking</font></p>
<p>进入容器，先后执行systemv_shm_wr和systemv_shm_rd，我们得到如下结果：</p>
<p><font face="Courier New">bash-4.1# systemv_shm_wr<br />
	SystemV Share Memory Create and Write Ok<br />
	bash-4.1# systemv_shm_rd<br />
	a b c d e f g h i j k l m n o p q r s t u v w x y z<br />
	SystemV Share Memory Create and Read Ok</font></p>
<p>在容器运行过程中，SystemV共享内存对象是可以持久化的。systemv_shm_wr退出后，数据依旧得以保留。我们接下来尝试一下重启container后是否还能读出数据：</p>
<p><font face="Courier New">$ sudo docker ps<br />
	CONTAINER ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IMAGE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COMMAND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CREATED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STATUS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NAMES<br />
	0a2f37bee6eb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shmemtest:v1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;/bin/bash&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8 minutes ago&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Up 8 minutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elegant_hawking&nbsp;&nbsp;&nbsp;&nbsp;<br />
	$ sudo docker stop 0a2f37bee6eb<br />
	0a2f37bee6eb<br />
	$ sudo docker start 0a2f37bee6eb<br />
	0a2f37bee6eb<br />
	$ sudo docker attach 0a2f37bee6eb<br />
	bash-4.1# systemv_shm_rd<br />
	SystemV Share Memory Create and Read Error: -1</font></p>
<p>程序返回-1，显然在shmget时就出错了，系统已经没有了key为&quot;5678&quot;的这个共享内存IPC对象了。也就是说当容器stop时，就好比我们的物理主机关机，docker将该容器对应的共享内存IPC对象删除了。</p>
<p>从原理上分析，似乎我们也能得出此结论：毕竟Docker container是通过kernel namespace隔离的，容器中的进程在IPC资源申请时需要加入namespace信息。打个比方，如果我们启动容器的进程pid(物理主机视角)是 1234，那么这容器内进程申请的共享内存IPC资源（比如key=5678）的标识应该类似于&ldquo;1234:5678&rdquo;这样的形式。重启容器 后，Docker Daemon无法给该容器分配与上次启动相同的pid，因此pid发生了变化，之前容器中的&quot;1234:5678&quot;保留下来也是毫无意义的，还无端占用系 统资源。因此，System V IPC在Docker容器中的运用与物理机有不同，这方面要小心，目前似乎没有很好的方法，也许以后Docker会加入全局IPC，这个我们只能等待。</p>
<p><b>二、Mmap映射共享内存</b></p>
<p>接下来我们探讨mmap共享内存在容器中的支持情况。mmap常见的有两类共享内存映射方式，一种映射到/dev/zero，另外一种则是映射到 Regular Fiile。前者在程序退出后数据自动释放，后者则保留在映射的文件中。后者对我们更有意义，这次测试的也是后者。</p>
<p>同样，我们也先来编写两个测试程序。</p>
<p><font face="Courier New">//mmap_shm_wr.go</font><br />
	<font face="Courier New">package main</font></p>
<p><font face="Courier New">//#include &lt;stdio.h&gt;<br />
	//#include &lt;sys/types.h&gt;<br />
	//#include &lt;sys/mman.h&gt;<br />
	//#include &lt;fcntl.h&gt;<br />
	//<br />
	//#define SHMSZ&nbsp;&nbsp;&nbsp;&nbsp; 27<br />
	//<br />
	//int shm_wr()<br />
	//{<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char c;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *shm = NULL;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *s = NULL;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int fd;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((fd = open(&quot;./shm.txt&quot;, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) == -1)&nbsp; {<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
	//<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lseek(fd, 500, SEEK_CUR);<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; write(fd, &quot;\0&quot;, 1);<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lseek(fd, 0, SEEK_SET);<br />
	//<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shm = (char*)mmap(shm, SHMSZ, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!shm) {<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -2;<br />
	//<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
	//<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close(fd);<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s = shm;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (c = &#39;a&#39;; c &lt;= &#39;z&#39;; c++) {<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *(s+(int)(c &#8211; &#39;a&#39;)) = c;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br />
	//}<br />
	import &quot;C&quot;</font></p>
<p><font face="Courier New">import &quot;fmt&quot;</font></p>
<p><font face="Courier New">func main() {<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i := C.shm_wr()<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if i != 0 {<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fmt.Println(&quot;Mmap Share Memory Create and Write Error:&quot;, i)<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fmt.Println(&quot;Mmap Share Memory Create and Write Ok&quot;)<br />
	}</font></p>
<p><font face="Courier New">//mmap_shm_rd.go</font><br />
	<font face="Courier New">package main</font></p>
<p><font face="Courier New">//#include &lt;stdio.h&gt;<br />
	//#include &lt;sys/types.h&gt;<br />
	//#include &lt;sys/mman.h&gt;<br />
	//#include &lt;fcntl.h&gt;<br />
	//<br />
	//#define SHMSZ&nbsp;&nbsp;&nbsp;&nbsp; 27<br />
	//<br />
	//int shm_rd()<br />
	//{<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char c;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *shm = NULL;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *s = NULL;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int fd;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((fd = open(&quot;./shm.txt&quot;, O_RDONLY)) == -1)&nbsp; {<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
	//<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shm = (char*)mmap(shm, SHMSZ, PROT_READ, MAP_SHARED, fd, 0);<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!shm) {<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -2;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
	//<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close(fd);<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s = shm;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 0;<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; SHMSZ &#8211; 1; i++) {<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&quot;%c &quot;, *(s + i));<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&quot;\n&quot;);<br />
	//<br />
	//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br />
	//}<br />
	import &quot;C&quot;</font></p>
<p><font face="Courier New">import &quot;fmt&quot;</font></p>
<p><font face="Courier New">func main() {<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i := C.shm_rd()<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if i != 0 {<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fmt.Println(&quot;Mmap Share Memory Read Error:&quot;, i)<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fmt.Println(&quot;Mmap Share Memory Read Ok&quot;)<br />
	}</font></p>
<p>我们通过go build构建上面两个程序，得到两个测试用可执行程序：mmap_shm_wr和mmap_shm_rd。下面我们来构建我们的测试用docker image，Dockerfile内容如下：</p>
<p><font face="Courier New">FROM centos:centos6<br />
	MAINTAINER Tony Bai &lt;bigwhite.cn@gmail.com&gt;<br />
	COPY ./mmap_shm_wr /bin/<br />
	COPY ./mmap_shm_rd /bin/</font></p>
<p>构建Docker image：&ldquo;shmemtest:v2&rdquo;：</p>
<p><font face="Courier New">$ sudo docker build -t=&quot;shmemtest:v2&quot; ./<br />
	Sending build context to Docker daemon 16.81 MB<br />
	Sending build context to Docker daemon<br />
	Step 0 : FROM centos:centos6<br />
	&nbsp;&#8212;&gt; 68edf809afe7<br />
	Step 1 : MAINTAINER Tony Bai &lt;bigwhite.cn@gmail.com&gt;<br />
	&nbsp;&#8212;&gt; Using cache<br />
	&nbsp;&#8212;&gt; c617b456934a<br />
	Step 2 : COPY ./mmap_shm_wr /bin/<br />
	&nbsp;&#8212;&gt; Using cache<br />
	&nbsp;&#8212;&gt; 01e2f6bc7606<br />
	Step 3 : COPY ./mmap_shm_rd /bin/<br />
	&nbsp;&#8212;&gt; 0de95503c851<br />
	Removing intermediate container 0c472e92809f<br />
	Successfully built 0de95503c851</font></p>
<p>启动一个基于该image的容器：<br />
	<font face="Courier New">$ sudo docker run -it &quot;shmemtest:v2&quot; /bin/bash</font></p>
<p><font face="Courier New">$ sudo docker ps<br />
	CONTAINER ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IMAGE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COMMAND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CREATED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STATUS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NAMES<br />
	1182f9eca367&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shmemtest:v2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;/bin/bash&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 11 seconds ago&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Up 11 seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; distracted_elion</font></p>
<p>进入容器，先后执行mmap_shm_wr和mmap_shm_rd，我们得到如下结果：</p>
<p><font face="Courier New">bash-4.1# mmap_shm_wr<br />
	Mmap Share Memory Create and Write Ok<br />
	bash-4.1# mmap_shm_rd<br />
	a b c d e f g h i j k l m n o p q r s t u v w x y z<br />
	Mmap Share Memory Read Ok</font></p>
<p>我们接下来尝试一下重启container后是否还能读出数据：</p>
<p><font face="Courier New">$ sudo docker ps<br />
	CONTAINER ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IMAGE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COMMAND&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CREATED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STATUS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PORTS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NAMES<br />
	1182f9eca367&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; shmemtest:v2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;/bin/bash&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; About a minute ago&nbsp;&nbsp; Up About a minute&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; distracted_elion&nbsp;&nbsp;&nbsp;<br />
	$ sudo docker stop 1182f9eca367<br />
	1182f9eca367<br />
	$ sudo docker start 1182f9eca367<br />
	1182f9eca367<br />
	$ sudo docker attach 1182f9eca36</font><font face="Courier New">7</font></p>
<p><font face="Courier New">bash-4.1# mmap_shm_rd<br />
	a b c d e f g h i j k l m n o p q r s t u v w x y z<br />
	Mmap Share Memory Read Ok</font></p>
<p>通过执行结果可以看出，通过mmap映射文件方式，共享内存的数据即便在容器重启后依旧可以得到保留。从原理上看，shm.txt是容器内 的一个文件，该文件存储在容器的可写文件系统layer中，从物理主机上看，其位置在/var/lib/docker/aufs/mnt /container_full_id/下，即便容器重启，该文件也不会被删除，而是作为容器文件系统的一部分：</p>
<p><font face="Courier New">$ sudo docker inspect -f &#39;{{.Id}}&#39; 1182f9eca367<br />
	1182f9eca36756219537f9a1c7cd1b62c6439930cc54bc69e87915c5dc8f7b97<br />
	$ sudo ls /var/lib/docker/aufs/mnt/1182f9eca36756219537f9a1c7cd1b62c6439930cc54bc69e87915c5dc8f7b97<br />
	bin&nbsp; dev&nbsp; etc&nbsp; home&nbsp; lib&nbsp; lib64&nbsp; lost+found&nbsp; media&nbsp; mnt&nbsp; opt&nbsp; proc&nbsp; root&nbsp; sbin&nbsp;&nbsp;&nbsp; selinux&nbsp;<big><b> shm.txt&nbsp;</b></big> srv&nbsp; sys&nbsp; tmp&nbsp; usr&nbsp; var</font></p>
<p style='text-align:left'>&copy; 2014, <a href='https://tonybai.com'>bigwhite</a>. 版权所有. </p>
]]></content:encoded>
			<wfw:commentRss>https://tonybai.com/2014/10/12/discussion-on-shared-mem-support-in-docker/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
