ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Uber Go 编码规范中文版:缩小变量作用域(Reduce Scope of Variables)实战指南

Uber Go 编码规范中文版:缩小变量作用域(Reduce Scope of Variables)实战指南 文档【免费下载链接】uber_go_guide_cnUber Go 语言编码规范中文版. The Uber Go Style Guide .项目地址https://gitcode.com/gh_mirrors/ub/uber_go_guide_cn点击查看免费下载在可能的情况下应当尽量缩小变量与常量的作用域Scope。本指南源自 Uber Go 语言编码规范 的 Reduce Scope of Variables 章节是规范Style部分中关于局部变量声明与作用域治理的核心条目之一。它直接回答了三个高频问题如何用 if 语句初始化缩小错误变量的生命周期、何时不应强行缩小作用域、以及常量到底该放函数内还是包级全局。读完本文你将掌握一套可落地的作用域收缩手法并能与其他规范条目如减少嵌套、本地变量声明、顶层变量声明组合使用写出更易读、更不易出错的 Go 代码。一、为什么要在意作用域作用域决定了标识符变量、常量、类型、函数在代码中的可见范围。作用域越小意味着标识符的存活窗口越短读者在阅读函数时需要考虑的上下文越少变量被误用、误覆盖的可能性越低变量占用的栈空间与逃逸分析负担更轻虽然这通常不是首要考量。因此本规范要求在可能的情况下尽量缩小变量和常量的作用域。注意前提是Where possible——如果缩小作用域会与减少嵌套Reduce Nesting产生冲突则不要缩小作用域。两条规范冲突时以减少嵌套优先。原因很直观嵌套过深的代码比一个稍大作用域的变量更难读。二、用 if 初始化语句收缩错误变量的作用域最常见的实践场景是错误处理。下面的写法把err变量的生命周期从整个函数缩短到了单个if语句块内Bad不推荐Good推荐gobrerr : os.WriteFile(name, data, 0644)brif err ! nil {br return errbr}brgobrif err : os.WriteFile(name, data, 0644); err ! nil {br return errbr}br右侧的写法利用了 Go 的if 语句初始化语句if statement with an init statementif关键字后、分号前的表达式只在该if块包括else块内可见。这样err只在判断失败的分支中出现不会泄漏到函数其余部分代码从三行缩到一行视觉噪声更小后续代码无需担心该err被无意复用或遮蔽。这种写法同样适用于循环中的错误处理例如与减少嵌套中先处理错误分支、提前返回/continue的模式配合for _, v : range data { if v.F1 ! 1 { log.Printf(Invalid v: %v, v) continue } v process(v) if err : v.Call(); err ! nil { return err } v.Send() }三、何时不应缩小作用域结果需要在 if 之外使用如果函数调用的结果需要在if之外继续使用就不要强行把声明塞进if。看下面的反例——为了把data、err放进 if 里代码被迫写出了嵌套的if...else可读性反而更差Bad不推荐Good推荐gobrif data, err : os.ReadFile(name); err nil {br err cfg.Decode(data)br if err ! nil {br return errbr }brbr fmt.Println(cfg)br return nilbr} else {br return errbr}brgobrdata, err : os.ReadFile(name)brif err ! nil {br return errbr}brbrif err : cfg.Decode(data); err ! nil {br return errbr}brbrfmt.Println(cfg)brreturn nilbr分析一下右侧好的版本好在哪data是cfg.Decode的输入必须在后续代码中可见所以data天然应该属于函数级作用域强行缩小反而制造嵌套两次if err : ...; err ! nil各自独立第一个err来自os.ReadFile与第二个err来自cfg.Decode互不污染第二次声明直接遮蔽了第一次的err但这种遮蔽是刻意且无害的——因为第一个err在return后已经死亡整个函数呈线性向下流动读文件 → 判错 → 解码 → 判错 → 打印 → 返回没有一层多余的花括号。这正对应了本规范开头的那句限制条件If you need a result of a function call outside of the if, then you should not try to reduce the scope.如果你需要在 if 之外使用函数调用的结果就不应尝试缩小作用域。从 Go 语言语义上讲if初始化语句声明的变量作用域从声明点开始、到对应if/else块结束为止Go 语言规范中称为 implicit block。因此结果是否需要在 if 之外存活就是判断能否收缩的硬性标准。此外这种线性写法也与不必要的 else 的精神一致——提前return错误路径让成功路径保持平铺。四、常量的作用域优先局部全局是例外规范对常量的要求更明确常量除非在多个函数或文件中使用或是包对外契约external contract的一部分否则不需要声明为全局。Bad不推荐Good推荐gobrconst (br _defaultPort 8080br _defaultUser userbr)brbrfunc Bar() {br fmt.Println(Default port, _defaultPort)br}brgobrfunc Bar() {br const (br defaultPort 8080br defaultUser userbr )br fmt.Println(Default port, defaultPort)br}br注意右侧版本中常量组const (...)被整体移入了函数体内。这样做的好处常量只在真正使用它的函数附近可见阅读Bar时无需跳出去查找全局定义局部常量不再需要_下划线前缀下划线前缀是未导出全局符号的标识约定命名可以更自然多个函数各自使用各自的局部常量避免全局命名空间膨胀。什么时候常量应该留在全局规范给出了两个全局常量的正当理由被多个函数或多个文件共用如果defaultPort在listen()、healthCheck()等多个函数中都要用到提升为包级常量是合理的是包对外契约的一部分即导出的常量例如const MaxRetries 3这是包的公共 API调用方需要引用它。如果常量仅被单个函数使用却以未导出全局形式存在还会带来一个隐患它与未导出全局符号加_前缀规则配合时容易引发命名遮蔽问题。该章节给出的例子正是全局defaultPort 8080与函数内局部defaultPort : 9090撞名、删掉某一行后静默用错值的场景。把常量移入函数局部这类问题从根源上消失。五、与相邻规范条目的组合使用缩小作用域不是孤立的规则它与规范中相邻的几条共同构成声明与作用域这一主题实践中常配套使用规范条目核心内容与作用域的关系本地变量声明显式赋初值用:零值场景用var决定局部变量用什么方式声明是缩小作用域的前提语法顶层变量声明顶层用var类型由表达式推导类型不符时才显式标注约束留在全局的那部分变量怎么写减少嵌套错误/特殊情况先处理提前 return 或 continue与缩小作用域冲突时本规则优先不必要的 else两分支都给同一变量赋值时合并为单个 if常与收缩 if 作用域同步发生未导出全局符号加_前缀包级未导出 var/const 用_开头全局符号的唯一例外错误值用err前缀见错误命名一个典型的组合改造流程是先用减少嵌套把if...else改写为先判错、提前 return的平铺结构再用 if 初始化语句if err : ...; err ! nil把错误变量的作用域压到最小最后检查常量仅单函数使用的移入函数体内多函数共用或对外导出的留在包级并按顶层变量声明与下划线前缀规则书写。六、小结作用域收缩的三条决策线把整个规范浓缩成一张决策清单错误变量能用if err : f(); err ! nil就地判断并返回的就地声明错误处理分支被压缩在 if 内部作用域最小。普通结果函数返回值需要在 if 之外继续使用的如后续计算依赖data老老实实声明在函数级保持线性流程不要为了收缩而制造嵌套——此时减少嵌套优先。常量默认放函数体内只有多函数/多文件共用或属于包对外契约两种情形才提升为全局。遵循这三条线代码的可读性、可维护性都会显著提升。规范原文位于 src/var-scope.md英文版可与中文仓库根目录 README.md 中的完整目录缩小变量作用域一节对照阅读相关配套条目见 减少嵌套、本地变量声明、不必要的 else 与 未导出全局符号加_前缀。赞分享文档【免费下载链接】uber_go_guide_cnUber Go 语言编码规范中文版. The Uber Go Style Guide .项目地址https://gitcode.com/gh_mirrors/ub/uber_go_guide_cn点击查看免费下载相关推荐Uber Go Style Guide 实战缩小变量与常量作用域Reduce Scope of Variables的工程实践Uber Go Style Guide 实战缩小变量与常量作用域Reduce Scope of Variables的工程实践 导读 在 Go 工程中变量文档教程代码质量LintChroma部署指南如何在服务器和集群上运行大规模蛋白质设计任务Chroma部署指南如何在服务器和集群上运行大规模蛋白质设计任务 Chroma是一个革命性的可编程蛋白质设计生成模型它让研究人员能够在服务器和计算集群上运行Uber Go语言编码规范中文版企业级Go开发最佳实践指南Uber Go语言编码规范中文版企业级Go开发最佳实践指南 Uber Go编码规范作为企业级Go开发的重要指南其诞生背景源于Uber在2010年代中期大规模文档上一篇SQL Server 内存优化 TempDB 元数据Memory-Optimized TempDB Metadata实战指南消除高并发元数据争用瓶颈下一篇番茄小说下载器完整指南三步搞定免费离线阅读创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表