分类 技术志 下的文章

AI 时代的初级工程师生存指南:别让“万能”的AI工具,毁掉你最宝贵的成长期

本文永久链接 – https://tonybai.com/2025/08/24/junior-engineer-survival-guide-in-ai-age

大家好,我是Tony Bai。

这是一个对初级工程师而言,最好也最坏的时代。

说它“最好”,是因为我们从未拥有过如此强大的工具。一名刚走出校门的毕业生,在入职的第一天,就能手握Claude Code、ChatGPT、Gemini Cli、Cursor、Copilot 等强大的 AI 编程助手。面对一个从未接触过的复杂任务——比如,为一个 Go 项目编写一个复杂的 gRPC 中间件——他可能只需要组织几次提示词,一段看起来完美、功能齐全、甚至带着单元测试的代码就诞生了。

那种“我什么都行”的强大感和即时满足感,是十年前的我完全无法想象的。

但说它“最坏”,也恰恰源于此。在这种令人沉醉的“魔幻”体验背后,一个直击灵魂的问题正在浮现:

这种惊人的“效率”,是在加速你的成长,还是在为你铺设一条通往“能力空心化”的捷径?

今天,我想和大家一起聊聊这个话题。这不仅是一份给初级工程师的生存指南,更是我们每一个身处 AI 浪潮中的技术人,都应该进行的深刻反思。

“浅层技能” vs “内功心法”:AI 正在拉开的差距

要理解 AI 带来的潜在风险,我们首先需要区分两种截然不同的技能:“浅层技能”“内功心法”

“浅层技能”,关注的是“是什么”(”What”)。在 AI 时代的初期,这主要体现为:

  • 擅长编写精妙的 Prompt。
  • 能快速地从 AI 处获得“能用”的代码片段。
  • 熟练地进行“复制-粘贴-修改”的“胶水”工作。

而如今,随着 Gemini CLI、Claude Code 这类编码智能体(Coding Agent)以及深度集成在 IDE 中的 AI 工具的兴起,这种“浅层技能”又演化出了一个更集成、也更具迷惑性的新形态。

“复制-粘贴”的动作消失了。取而代之的,是 Agent 直接读取你的整个代码库,然后给你一个可以直接应用的变更集(diff)。在这里,“浅层技能”表现为:

  • 将高阶的、模糊的任务指令(‘重构这个文件’、‘修复这个bug’)下发给 Agent。
  • 对 Agent 提出的变更集进行表面化的审查——检查代码风格是否一致、命名是否规范,但缺乏对底层逻辑、性能陷阱和安全隐患的深度洞察。
  • 最终,熟练地点击‘应用’(Apply)或‘接受’(Accept)按钮,成为一个高效的“变更批准员”

你看,无论是“复制代码”还是“批准变更”,其本质是相通的:你依然只停留在知道“是什么”,而没有深入到“为什么”。 你知道这段由 Agent 修改的代码能工作,但你很可能依然不清楚它背后的原理。这种新模式甚至更危险,因为它让你感觉更“专业”,更容易在不知不觉中放弃思考。

“内功心法”,关注的则是“为什么”(The “Why”)“怎么做”(The “How”)。这包括:

  • 设计模式:为什么在这里 AI 选择用工厂模式,而不是单例模式?这两种模式的权衡是什么?
  • 数据结构与算法:AI 生成的这个函数,其核心数据结构是什么?它的时间复杂度和空间复杂度在各种情况(最好、最坏、平均)下分别是多少?
  • 架构权衡:这段看似独立的代码,被集成到系统中后,是会提升整个系统的内聚性,还是会引入一个危险的耦合点?
  • 调试能力:当这段“完美”的 AI 代码,在生产环境中因为一个罕见的并发条件而出现诡异的 Bug 时,你有能力深入其中,定位并解决问题吗?

“浅层技能”决定了你使用工具的熟练度,而“内功心法”则决定了你作为一名工程师的能力天花板

“舒适”的代价:正在累积的“认知负债”

问题在于,AI 工具太“舒适”了。它让我们能轻易地绕过那些艰难的、需要深度思考的“内功”修炼,直接获得“浅层”的结果。这种舒适感,正在让我们不知不觉地背上沉重的“认知负债”(Cognitive Debt)

这个概念精辟地描述了一种权衡:我们用即时的便利,换取了长期的批判性思维、记忆力、以及创造性自主权的丧失。 你正在向机器借用脑力,但这笔债,未来需要连本带利地偿还。

最近的一项科学研究,用数据血淋淋地揭示了这一点。研究者将参与者分为三组写论文:纯脑力组、搜索引擎组和 LLM 组。结果令人震惊:

在 LLM 组中,83% 的参与者在写完论文后,几乎无法复述出自己文章中的任何观点(见下图)。而在另外两组,几乎每个人都能做到。

这证明了,当我们把思考过程完全外包给 AI 时,知识并没有真正“流经”我们的大脑,我们只是成为了一个信息的“搬运工”。

这背后,是纳西姆·塔勒布在其著作《反脆弱》中提到的深刻哲理:小的压力和不适,会让我们变得更强大。

  • 肌肉,需要通过举起沉重的杠铃,在撕裂和修复中才能生长。
  • 我们的大脑,同样需要通过“精神举重”——也就是主动思考、艰难探索、反复试错的“摩擦力”——才能成长。

而初级工程师的职业生涯前三年,正是进行这种“精神举重”、构建个人能力护城河最宝贵的黄金时期。如果在这个阶段,你沉迷于 AI 带来的舒适感,持续累积“认知负债”,无异于在一个本应最大化“肌肉增长”的年纪,选择了全程坐轮椅。

其长期危害是显而易见的:

  1. 成长停滞:解决问题的“认知肌肉”因缺乏锻炼而萎缩。
  2. 危险的“信心差”:你产生了一种“我能搞定任何代码”的虚假自信,但这与“我能维护和解释任何我写的代码”的真实能力之间,存在着巨大的鸿沟。这在团队协作和处理线上故障时,是极其危险的。
  3. 沦为“API 粘合工”:长期以往,你可能会彻底丧失从零开始构建系统的能力,沦为只会将 AI 生成的黑箱代码块“粘合”在一起的低阶操作员,失去了真正的工程创造力和不可替代性。

“破局”指南:如何成为 AI 的主人,而非奴隶?

那么,我们该如何打破这个困局?关键在于心态的转变方法的调整。你需要将 AI 从一个无所不知的“神谕”(Oracle),转变为一个需要你引导和挑战的“陪练”

这里有四条具体的实战法则:

法则一:“先思后问”法则

在向 AI 提问前,强迫自己先进行独立思考。用纸笔、伪代码或注释,勾勒出你自己的解决方案轮廓。哪怕这个方案很粗糙,甚至可能是错的,这个思考的过程本身就是一次宝贵的“精神举重”。

然后,你可以这样做:

“不要让 AI 直接为你解题;相反,提供你自己的解法,让它解释你可能错在哪里,或者有哪些可以改进的地方。”

通过这种方式,你把 AI 从一个“答案机”变为一个能启发你、挑战你的“批判性思维伙伴”。你始终是思考的主导者。

法则二:“刨根问底”法则

永远不要满足于 AI 给出的第一份“能用”的代码。对它生成的每一段关键代码,都要像对待一位资深同事的 Code Review 意见一样,进行苏格拉底式的反复追问

  • “你为什么选择这种数据结构?它和另一种方案相比,优劣势分别是什么?”
  • “这段代码的时间复杂度和空间复杂度是多少?在什么情况下会达到最坏情况?”
  • “请为这段代码生成五个可能会导致它出错的边缘案例(corner cases)。”
  • “这段代码遵循了哪些设计模式?请为我解释这个模式的核心思想。”

通过这种刨根问底,你把 AI 从一个“代码生成器”,变成了一个免费的、24小时在线的、极具耐心的私人导师

法则三:“刻意练习”法则

定期进行“无 AI 编程”的刻意练习。这就像健身房里的“力量训练日”。给自己设定一些小项目、算法题,或者工作中的某个非紧急模块,规定自己在不使用任何 AI 代码生成辅助的情况下,从零开始完整地实现它。

这个过程可能会让你感到“不适”,速度会很慢,甚至会碰壁。但请记住塔勒布的教诲:不适感不是麻烦,而是训练场。 这正是你构建底层能力、“流血流汗”的真实成长过程。

法则四:“源码为师”法则

当 AI 生成了一段使用了你从未见过的库函数或框架特性的代码时,不要只满足于知道“怎么用”。花15分钟时间,去看看那个函数或特性的源码实现。

这是理解其背后原理、设计哲学和实现细节的最直接方式。AI 可以为你指出一条通往宝藏的道路,但路边的风景和地下的矿藏,需要你自己去探索和挖掘。

你的不可替代性,藏在 AI 的“盲区”里

遵循以上法则,你会发现,AI 不仅不会成为你成长的障碍,反而会成为你成长的强大加速器。更重要的是,它会帮助你将精力聚焦在那些 AI 永远无法取代的、真正体现工程师价值的领域——也就是 AI 的“盲区”。

  • 深度理解业务:AI 不懂你的用户,不懂你的商业模式。将技术与业务场景深度结合,提供有洞察力的解决方案,这是你的核心价值。
  • 系统性思考:AI 能生成一个函数,但它尚无法设计一个健壮、可扩展、可维护的大规模生产级系统。培养自己的架构思维和全局视野,是你拉开差距的关键。
  • 人际协作与沟通:理解团队成员的需求,清晰地阐述技术方案的利弊,组织有效的讨论,推动项目落地。这些“软技能”,在 AI 时代变得比以往任何时候都更加重要。

小结:别在黄金时代,选择一条最容易的路

职业生涯的初期,是一个人构建个人“能力护城河”最关键的时期。在这个阶段,最宝贵的不是表面的“效率”,而是“成长深度”

AI 时代,给了我们前所未有的强大工具,但工具的价值,永远取决于使用者的智慧。

所以,请警惕那些让你过于舒适的捷径。不要在最需要“扎马步”的年纪,沉迷于“轻功”带来的快感。 真正的成长,永远伴随着求索的痛苦和突破的喜悦。让我们去拥抱那些有益的“摩擦力”,掌握那些 AI 无法生成的“内功心法”。

选择那条更难、但更有价值的路,你才能在未来的技术浪潮中,真正地立于不败之地。

参考资料

-《Your Brain on ChatGPT: Accumulation of Cognitive Debt when Using an AI Assistant for Essay Writing Task》- https://arxiv.org/pdf/2506.08872v1


你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?

  • 想写出更地道、更健壮的Go代码,却总在细节上踩坑?
  • 渴望提升软件设计能力,驾驭复杂Go项目却缺乏章法?
  • 想打造生产级的Go服务,却在工程化实践中屡屡受挫?

继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!

我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。

目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!


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

泛型重塑 Go 错误检查:errors.As 的下一站 AsA?

本文永久链接 – https://tonybai.com/2025/08/23/proposal-errors-asa

大家好,我是Tony Bai。

Go 1.13 引入 errors.Is 和 errors.As 以来,Go 语言的错误处理进入了一个结构化、可追溯的新时代。然而,errors.As 的使用方式,对于追求代码简洁与优雅的 Gopher 而言,始终存在一丝“不和谐”:开发者必须预先声明一个目标错误类型的变量,然后将其指针传入函数。

随着 Go 1.18 泛型的正式落地,一个酝酿已久的问题浮出水面:我们能否利用类型参数,彻底重塑这一核心错误检查机制,终结那些恼人的样板代码?GitHub 上的 Issue #51945 正是这场变革的中心舞台。它不仅是一个新函数AsA的提案,更深刻地揭示了 Go 社区是如何在 API 设计、性能、向后兼容性与语言哲学之间反复权衡,以决定 errors.As 的未来。那么,AsA 会是 errors.As 的下一站吗?在这篇文章中,我就和大家一起来看一下Go社区和Go团队针对这一提案的讨论和决策过程。

现状之痛:errors.As 的人体工程学难题

要理解为何需要“重塑”,我们必须先审视 errors.As 带来的便利与痛点,我们先来看一下现状:

// Go 1.13 至今的标准模式
err := someOperation()
if err != nil {
    var myErr *MyCustomError
    if errors.As(err, &myErr) {
        // myErr 在这里可用,但它的声明却在 if 语句之外
        // ...处理 myErr...
    }

    var otherErr *OtherError
    if errors.As(err, &otherErr) {
        // ...处理 otherErr...
    }
    // ...
}

这种模式存在几个显而易见的痛点:

  1. 样板代码: var myErr *MyCustomError 这一行是纯粹的样板代码。
  2. 变量作用域泄露: myErr 的作用域超出了它真正被需要的 if 块,这在 Go 中通常被认为是不够优雅的设计。
  3. C 语言风格的“输出参数”: 通过指针参数来“返回”一个值,是 C 语言的常见模式,但在 Go 中,我们更习惯于通过多返回值来处理。

正是这些“不和谐”之处,催生了用泛型来重塑 errors.As 的强烈动机。

泛型之力:三大核心优势重塑错误检查

提案的核心,是引入一个利用类型参数的新函数,社区讨论最终倾向于命名为 AsA。这个新函数将彻底改变错误检查的写法,使其更符合 Go 开发者熟悉的“逗号, ok”模式:

// 提案中的理想模式
err := someOperation()
if err != nil {
    if myErr, ok := errors.AsA[*MyCustomError](err); ok {
        // myErr 的作用域被完美限制在此 if 块内
        // ...处理 myErr...
    } else if otherErr, ok := errors.AsA[*OtherError](err); ok {
        // ...处理 otherErr...
    }
    // ...
}

这场“重塑”的背后,是泛型带来的三大核心优势:

优势一:人体工程学与代码可读性

这是最直观的优点。新的 if shortVarDecl, ok := … 形式是 Go 语言中最深入人心的模式之一,用于类型断言、map 查询等众多场景。将错误检查统一到这个模式下,降低了开发者的心智负担。

尽管有社区成员指出现有的 errors.As 也可以通过 if pe := new(os.PathError); errors.As(err, &pe) 这种巧妙的写法实现单行和作用域限制,但其他成员普遍认为这种写法“非常微妙”、“难以阅读”,且容易误用。这恰恰反衬出泛型版本在清晰度和直观性上的巨大优势。

优势二:编译时类型安全

这是泛型版本一个被低估但至关重要的优势。errors.As 的第二个参数类型是 any(interface{}),这意味着编译器无法在编译时对其进行严格的类型检查。任何不满足“指向 error 实现类型的非空指针”这一约束的用法,都只能在运行时 panic 或被 go vet 捕获。

而泛型版本则将这个检查提前到了编译时。类型参数 T 被约束为 error,任何不满足此约束的类型参数都会导致编译失败。这无疑是向 Go 的核心价值——静态类型安全——迈出的重要一步。

优势三:显著的性能提升

这可能是最令人意外,也是最有说服力的论据。errors.As 的实现严重依赖反射,以便在运行时处理 any 类型的 target。反射在 Go 中是出了名的慢。

有社区成员提供了他的开源库 errutil 中的纯泛型实现 Find,并给出了详尽的 benchmark 数据。其核心思想是,在泛型函数内部,可以直接使用类型断言 (err.(E)),完全绕开反射。并且,其提供的 benchmark 结果令人震惊:在绝大多数场景下,纯泛型实现的性能比 errors.As 快 50% – 70%。此外,由于避免了为 target 变量在堆上分配内存(new(E)),纯泛型版本在很多情况下可以做到零堆分配

前路挑战:从 switch 困境到 API 哲学的权衡

尽管优势明显,但“重塑”之路并非一帆风顺。Go 核心团队和社区的审慎讨论,揭示了在标准库中引入新 API 的复杂性。

考量一:历史的包袱与设计的初心

一些Go核心团队成员提及,在 errors.As 最初的设计阶段,rsc (Russ Cox) 曾认为,var myErr *MyError 的显式声明,虽然冗长,但明确地向读者展示了代码正在寻找的错误类型,具有清晰性的优点。这体现了 Go 早期设计中对“明确优于隐晦”的极致追求。

考量二:switch 语句的困境

这是泛型版本最主要的“人体工程学”短板。errors.As 可以非常优雅地与 switch 语句结合,形成强大的多错误类型处理模式:

var myErr *MyCustomError
var otherErr *OtherError

switch {
case errors.As(err, &myErr):
    // ...
case errors.As(err, &otherErr):
    // ...
}

然而,返回 (T, bool) 的泛型函数无法直接用在 case 语句中,这破坏了一种现有的、被广泛接受的优雅模式。

考量三:API 的膨胀与命名难题

在标准库中增加一个与现有函数功能高度重叠的新 API,是一项需要慎之又慎的决定。它会带来“API 膨胀”的问题,并引发关于命名的激烈讨论。从最初的 IsA,到社区热议的 AsA、AsOf、Find、Has,每一个名字都有其合理性与不足。

小结:尘埃落定:AsA,迈向未来的下一站?

经过长达数年的讨论、辩论与社区探索,在 neild 的总结陈词下,提案目前已经收敛并被 Go 团队选中,进入了 “Active” 审查阶段。这标志着 Go 官方已经基本认可了引入泛型 errors.As 的价值。

最终的提案形态如下:

package errors

// AsA finds the first error in err's tree that has the type E, and if one is found, returns that error value and true.
// Otherwise it returns the zero value of E and false.
func AsA[E error](err error) (_ E, ok bool)

这个版本的暂时胜出,也是多方权衡的结果:

  • 双返回值形式 (_ E, ok bool) 在人体工程学和性能上全面优于指针参数形式。
  • AsA 的命名最大程度上保留了与 As 的关联性。
  • 尽管存在 switch 语句的短板,但其在 if 语句中的巨大优势、编译时类型安全和显著的性能提升,最终压倒了所有顾虑。

这场关于 errors.As 泛型化的深度辩论,生动地展示了 Go 语言的演进过程:它不是一蹴而就的激进变革,而是在尊重历史、充分听取社区声音、深入权衡利弊后,做出的稳健而有力的前行。而泛型的引入,也正在为 Go 社区提供一个重新审视和打磨既有 API 的宝贵契机。让我们有理由相信 Go 的错误检查也将因此被成功“重塑”,变得更加安全、高效和优雅。

资料链接:https://github.com/golang/go/issues/51945


你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?

  • 想写出更地道、更健壮的Go代码,却总在细节上踩坑?
  • 渴望提升软件设计能力,驾驭复杂Go项目却缺乏章法?
  • 想打造生产级的Go服务,却在工程化实践中屡屡受挫?

继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!

我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。

目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!


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

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言进阶课 Go语言精进之路1 Go语言精进之路2 Go语言第一课 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats