「笔记003」Go高质量编程
核心要求
- 正确可靠:代码功能实现准确、逻辑严密。
- 简介清晰:代码结构与实现尽可能简洁,逻辑直观。
- 边界条件完备:考虑所有可能的输入及场景,保证功能覆盖边界情况。
- 异常处理:通过有效的异常处理机制,提升代码稳定性。
- 可读性与可维护性:代码应清晰易懂,便于他人理解和修改。
代码规范细则
1. 代码格式化
gofmt
: 统一代码风格,符合Go官方规范。goimports
: 在gofmt
基础上自动管理依赖包。
2. 注释规范
- 注释功能:
- 解释代码的作用:注释要描述代码的目的和作用。
- 解释实现细节:解释代码的逻辑或设计背后的思路。
- 阐明原因:说明为何采取当前实现方式。
- 指出潜在错误:记录代码运行时可能遇到的问题。
- 注释范围:
- 公共符号(变量、常量、函数、结构体)。
- 复杂、难懂的逻辑,无论公私范围。
- 库函数中任何公共功能(实现接口的方法除外)。
3. 命名规范
- 变量命名:
- 简洁明了,避免冗长。
- 缩略词全大写(如HTTP),私有变量首字母小写。
- 距离使用越远,名称应提供更多上下文信息。
- 函数命名:
- 避免重复包名信息。
- 如果返回的对象类型明显,可省略类型信息。
- 包命名:
- 小写字母,无下划线、无大写。
- 避免与标准库冲突(如
bufio
)。 - 使用单数形式(如
encoding
)。 - 避免缩写,除非广泛认可(如
fmt
)。
- 核心原则:
- 减少认知负担。
- 增强代码上下文表达力。
4. 流程控制
- 减少嵌套:
- 用
if-return
优化if-else
结构。 - 尽早处理异常/特殊情况,减少后续逻辑复杂度。
- 用
- 直线逻辑:
- 避免冗长嵌套。
- 按屏幕自上而下编排逻辑,便于阅读。
5. 错误和异常处理
- 简单错误:
- 不复用的简单错误,直接用
errors.New
或fmt.Errorf
。
- 不复用的简单错误,直接用
- 错误包装与解包:
- 用
fmt.Errorf
的%w
关键字构建错误链。 - 用
errors.Is
判断特定错误。 - 用
errors.As
提取特定类型错误。
- 用
panic
与recover
:panic
:不建议在业务代码中使用,适用于程序初始化阶段的不可逆错误。recover
:只能在defer
函数中使用,适用于捕获panic
并恢复程序运行。
6. defer
使用注意事项
defer
语句在函数返回前执行。- 多个
defer
语句后进先出(栈行为)。 - 在分支中使用
defer
时,所有分支的defer
按调用顺序压栈。
示例与扩展
1. 简单错误处理
if err != nil {
return fmt.Errorf("failed to read file: %w", err)
}
2. 错误链与判断
var pathError *fs.PathError
if errors.As(err, &pathError) {
fmt.Println("Specific error type detected:", pathError.Path)
}
if errors.Is(err, os.ErrNotExist) {
fmt.Println("File does not exist")
}
3. defer
的行为
func exampleDefer() {
defer fmt.Println("Executed last")
defer fmt.Println("Executed second")
fmt.Println("Executed first")
// Output:
// Executed first
// Executed second
// Executed last
}
注意
- 遵循最小必要原则,减少代码冗余。
- 优先使用Go语言的内置特性,如
defer
和error
机制。 - 通过注释和清晰命名,提升代码的表达能力,降低沟通成本。