Golang 开发“疑难杂症”解决办法 🤔⁉️
Go 开发中容易出现的错误案例分析与解决办法
工程架构不合理
- 混乱的代码作用域导致 变量隐藏
- 代码通过编译,但数据并没有赋值到预期的变量
- 采用局部临时变量(
:=
),再赋值给目标变量 - 直接采用赋值操作符赋值给目标变量(可读性和性能较好,还能抽离统一处理
err
) - Go 变量:内存中可寻址、寻址是有范围的
- 不必要的 嵌套 导致代码可读性差
- 软件的思维模型是对系统行为的内部表达方式
- 影响可读性的一个关键方面:嵌套层的数量
- 把正确的代码路径向左对齐,以方便查看预期的执行流
- 异常情况通过
if
表示,去else
,减少代码块
- 滥用
init
函数 使代码流难以管理- 需要进行错误管理、涉及状态的逻辑不依赖
init
函数 init
函数不便进行单元测试
- 需要进行错误管理、涉及状态的逻辑不依赖
- 过度使用 getter 和 setter 导致 代码淹没风险
- getter 和 setter 的优点:封装、隐藏、调试
- 不需要就不用这种方式,保持语言简洁特性
- 使用不必要的抽象导致 接口污染
- 接口越大,抽象越弱。— Rob Pike
- 何时使用接口:
- 常见的行为,如
sort.Interface
- 解耦(设计模式,组件可替换)
- 限制行为(语义上通过接口类型来限制特定行为)
- 常见的行为,如
- 发现抽象,而不是创建抽象(使用接口,而不是随意创建接口)
- 不要用接口进行设计,要发现他们。— Rob Pike
项目难维护难扩展
- 不要 过度抽象,要根据客户端(功能调用方)的实际需求
- 做什么要保守,接收什么要自由
- 尽可能不要返回接口,而是返回具体的实现;接收接口
- 也有例外,比如返回
error
接口
any
代表着 nothing,避免 过度泛化 错误来规避any
(interface{}
) 不能传达任何信息encoding/json
的Mashal
形参是any
database/sql
的QueryContext
查询 query 是any
- 使用 泛型,避免运行时开销与代码冗余,泛型用法:
- 数据结构、提取行为、处理任何类型的 slice、map 和 channel 的函数
- 当调用类型参数的方法时、当泛型使代码更加复杂时不该使用泛型
- 结构体字段 类型嵌入、接口与嵌入
- 避免方法被提升导出(不额外命名私有变量,而是直接嵌入)
- 嵌入对比 OOP 中的子类化(组合和继承的区别)
- 类型嵌入约束:他不是语法糖、不应该提升本应该隐藏的元素