2026/6/10 17:17:22
网站建设
项目流程
用邮箱地址做网站域名好吗,上海html5网站建设,网站建设公司推来客网站系统怎么样,wordpress 4.7.5 中文大家好#xff0c;我是Tony Bai。“有哪些‘不要做’的教训#xff0c;是你花了好几年才学会的#xff1f;”近日#xff0c;在 r/golang 社区#xff0c;这个简单的问题#xff0c;引爆了一场关于 Go 语言“反模式”与“最佳实践”的集体反思。帖子下数百条评论#xf…大家好我是Tony Bai。“有哪些‘不要做’的教训是你花了好几年才学会的”近日在 r/golang 社区这个简单的问题引爆了一场关于 Go 语言“反模式”与“最佳实践”的集体反思。帖子下数百条评论汇集了无数 Gopher 在真实项目中用“血与泪”换来的宝贵经验。这些教训往往不是关于某个高深的算法而是关于那些看似“理所当然”却在不经意间为代码埋下地雷的日常习惯。这篇文章正是对这场集体智慧的一次系统性梳理。我们从中提炼出 10 条最核心的“不要做”法则它们如同一份“避坑指南”能帮助你绕开那些最常见的陷阱更快地从一名“会写 Go 的程序员”成长为一名“懂 Go 的工程师”。不要过度封装包Dont overpackage things初学者往往有一种冲动想把代码组织成“语义化”的、层层嵌套的包结构。internal/models,internal/services,internal/repositories…… 这种源自其他语言如 Java的模式在 Go 的世界里往往是一种过早的、不必要的复杂性。社区忠告从一个main.go文件开始。努力思考是否真的有必要将代码拆分到多个文件/包中。Go 的包其主要目的是封装和依赖管理而不是单纯的文件夹分类。在小型或中型项目中一个清晰的、扁平的包结构远比一个复杂的“企业级”目录树更易于维护。不要滥用 channel 和 goroutineDont just add in channels并发是 Go 的“名片”这使得许多开发者尤其是新手有一种“锤子心态”——看到任何问题都想用 goroutine 和 channel 来解决。然而不必要的并发是复杂性和 bug 的温床。社区忠告先问“是否需要”你真的需要并发吗如果不需要在线程间传递消息你可能根本不需要 channel。一个简单的sync.WaitGroup或sync.Mutex在很多场景下都比 channel 更简单、更直接。并发不是免费的Go 让创建 goroutine 变得异常简单但这并不意味着它是零成本的。过多的 goroutine 会增加调度器的负担而 channel 的滥用则会使数据流变得难以追踪和调试。不要盲目追求 DRYDont be zealous about DRYDRY 是编程的基本原则但在 Go 的哲学中它有一个更重要的“上级”——清晰性。为了消除几行重复代码而引入一个复杂的接口或一个晦涩的辅助函数往往得不偿失。社区忠告“一点点复制胜过一点点依赖 (a little copy-paste is better than a little dependency)。” 当你发现自己在为了 DRY 而绞尽脑汁时请停下来问问自己这份重复是否真的带来了维护上的痛苦如果不是那么接受它可能是一个更明智的选择。不要在同一个 PR 中既重构又添加新功能Dont refactor and add features in the same PR在添加一个新功能时顺手“优化”一下周围的代码这看起来很高效。但实际上这会让 Code Review 变得异常痛苦。Reviewer 无法清晰地分辨哪些改动是为新功能服务的哪些是纯粹的重构。这不仅增加了审查的难度也提高了引入新 Bug 的风险。社区忠告遵循“童子军军规”——“让营地比你来时更干净”——是好的。但请将它分解为两个独立的、目标明确的 PR一个只做重构另一个基于重构后的代码只添加新功能。不要跳过写测试“就这一次”Dont skip writing tests just this once这是所有开发者都曾屈服过的诱惑。“这个改动太小了”、“我百分之百确定它是对的”、“项目赶时间”…… 每一次“就这一次”的妥协都在为未来的“技术雪崩”添砖加瓦。社区忠告将测试视为代码不可分割的一部分。在 Go 中编写测试是如此简单和自然以至于没有任何借口可以跳过它。你今天节省下来的 10 分钟可能会在未来让你或你的同事花费数天时间去调试一个本可避免的生产问题。不要害怕使用sync.Condchannel非常强大但它并非解决所有并发同步问题的“银弹”。社区中有一种“反sync”的情绪认为所有同步都应该用 channel 来完成。社区忠告sync.Cond是一个被低估了的、极其强大的并发原语。当你需要基于某个特定条件来唤醒一个或多个等待的 goroutine时例如一个任务队列的消费者在队列为空时等待sync.Cond往往比用 channel 实现的复杂信令机制要更简单、更高效。不要因为不熟悉就回避它。不要返回接口Returning interfaces. Dont do it.在函数签名中返回一个接口看似遵循了“依赖倒置”的高级原则甚至觉得这样更“灵活”。但实际上这往往是一种过早的、有害的抽象。它剥夺了用户访问底层具体类型特有功能的能力并且如果未来需要添加新方法接口的变更会极其痛苦。社区忠告遵循 Go 的经典谚语“接收接口返回结构体 (Accept interfaces, return structs)。”接收接口让你的函数接收一个只包含其所需最小方法集的接口作为参数。这使得你的函数更容易被测试和复用你可以传入任何满足该接口的实现包括 Mock 对象。返回结构体让你的函数返回一个具体的类型通常是指针。这给了调用者最大的灵活性。经典范例看看标准库中的os.Open它返回的是*os.File具体结构体而不是io.Reader接口。为什么这样做因为*os.File不仅能读Read还能关闭Close、获取状态Stat、甚至改变权限Chmod。灵活性如果它返回的是接口用户就无法使用Chmod等特有功能了。而返回结构体用户既可以使用其全部功能也可以在需要时轻松地将其赋值给io.Reader接口来使用。这就是“返回结构体”带来的自由。(注只有当返回的类型是包内私有的、不希望外部直接访问的实现细节时返回接口才是有意义的例如context.WithCancel返回的是Context接口。)不要过度依赖依赖Dont add dependencies without vetting为了解决一个小问题而引入一个庞大的、闪亮的第三方库。这在 Node.js 生态中很常见但在 Go 社区这通常被视为一种“危险信号”。社区忠告先求诸标准库在引入任何依赖之前先问问自己这个问题标准库真的解决不了吗审慎评估如果必须引入依赖请仔细评估它它的依赖树有多深社区是否活跃维护者是否可靠一个简单的依赖可能会为你整个项目带来潜在的供应链安全风险和维护噩梦。不要盲从Dont do [or not do] something simply because an authoritative voice recommended it盲目地遵循某个“大神”、某篇“爆款”博客文章、或者某个“权威”推荐的模式而没有结合自己的具体场景进行批判性思考。社区忠告上下文决定一切。YAGNI(You Arent Gonna Need It) 是一个好原则但有时你确实需要提前设计。微服务很好但有时单体就是最佳选择。没有银弹。最好的实践是那些在你的团队、你的项目中被证明行之有效的实践。不要忘记代码是给人读的忘记了代码的最终读者是人类而不是编译器。编写只有自己能看懂的“聪明”代码或者忽略文档和注释的重要性。社区忠告编写能让你的未来“自已”不会痛骂你的代码。好的设计不是增加而是保持本质的简单。代码即是负债 (Code is liability)。不要忽视清晰文档的重要性。小结在“坑”里成长这份清单远非全部。社区的讨论中还充满了诸如“不要用singleton来做mock”、“不要滥用init函数”、“不要在疲劳时 Review 代码”等无数宝贵的经验。它们共同指向了一个核心思想成为一名优秀的 Go 工程师其过程不仅仅是学习语言的特性更是一个不断反思、不断“踩坑”、并从“坑”中总结出属于自己“不要做”清单的修炼过程。希望这份来自社区的集体智慧能让你在这条路上走得更稳、也更远。资料链接https://www.reddit.com/r/golang/comments/1pib68y/whats_a_dont_do_this_lesson_that_took_you_years/如果本文对你有所帮助请帮忙点赞、推荐和转发点击下面标题干货- 写出让同事赞不绝口的Go代码Reddit工程师总结的10条地道Go编程法则- Go 跌出 TIOBE 前十别被排名骗了这才是它的真实地位- Go项目设计的“七宗罪”警惕那些流行的“反模式”- Go 模块构建与依赖管理我们到底在“折腾”什么- 你的 Go 测试还停留在“演员对台词”吗- 为什么 Go 在悄悄地做 Rust 做不到的事保持简单- “我曾想付钱给 Google 去工作”—— Russ Cox 深度访谈Go 的诞生、演进与未来 还在为“复制粘贴喂AI”而烦恼我的新极客时间专栏《AI原生开发工作流实战》将带你告别低效重塑开发范式驾驭AI Agent(Claude Code)实现工作流自动化从“AI使用者”进化为规范驱动开发的“工作流指挥家”扫描下方二维码开启你的AI原生开发之旅。