课程目录
- 高质量编程
- 性能调优实战
高质量编程
编写的代码能够达到正确可靠、简洁清晰的目标可称之为高质量代码
需要考虑
- 边界条件问题
- 异常情况处理问题
- 易读易维护
编程原则
-
简单性:消除多余的复杂性,否则难以维护和改进
-
可读性:详细注释+清晰逻辑
-
生产力:团队合作的高效
编码规范
-
代码格式 (gofmt 格式化代码 ; goimports 格式化代码 + 依赖管理)
-
注释
- 解释代码作用
- 解释代码如何实现的
- 解释代码实现的原因
- 解释代码的特殊情况
Good code has lots of comments, bad code requires lots of comments
代码是最好的注释, 逻辑清晰的代码本身对阅读者来说就是一种注释
注释应该提供代码中未提到的上下文信息
- 包中声明的每个公共的符号:变量、常量、函数以及结构都需要添加注释
- 任何既不明显也不简短的公共功能必须予以注释
- 无论长度或复杂程度如何,对库中的任何函数都必须进行注释
- 不需要注释实现接口的方法,因为对理解代码没什么帮助(follow)
// read implements the io.Reader interface
func (r *FileReader) Read(buf []byte) (int, err)
- 命名规范
-
简洁胜于冗长
-
缩略词全大写(ServeHTTP), 但当其位于变量开头并且不需要导出时,使用全小写(xmlHTTPRequest)
-
变量距离其被使用的地方越远,则需要携带越多的上下文信息 (全局变量在其名字中需要更多的上下文信息, 使得在不同的地方可以轻易辨认出其含义)
-
function 命名规范
规范示例: 在 http 包中创建服务函数, 应该使用 Serve 而不是 ServeHTTP (和包中重复)
- 包名命名规范
好的命名规范,可以降低阅读理解代码的成本,重点考虑上下文信息,设计简洁清晰的名称
- 控制流程
- 错误和异常处理
- errors.Is 判断错误链中某种错误是否存在
data, err := lockedfile.Read(targ)
if errors.Is(err, fs.ErrNotExit) { ... }
- errors.As 检索错误链中是否存在某种错误并进行相应处理
if _, err := os.Open("non-existing); err != nil {
var pathError *fs.PathError
if errors.As(err, &pathError) {
fmt.Println("failed at path:", pathError.Path)
} else {
fmt.Println(err)
}
}
- panic 异常处理
func main() {
// ..
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := sarama.NewConsumerGroup(strings.Split(brokers, ","), group, config)
if err != nil {
log.Panicf("error creating consumer group: %v", err)
}
...
}
// Panicf is equivalent to Printf() + panic()
func Panicf(format string, v ...interface{}) {
s := fmt.Sprintf(format, v...)
std.Output(2, s)
panic(s)
}
- recover 在 defer 函数中捕获 panic 异常,防止程序崩溃
func (s *ss) Token(skipSpace bool, f func(rune) bool) (tok []byte, err error) {
defer func() {
if e := recover(); e != nil {
if se, ok := e.(scanError); ok {
err = se.err
} else {
panic(e)
}
}
}()
// 在程序 panic 退出前,将 panic 捕获,使程序正常返回退出
...
}
func (t *treeFS) Open(name string) (f fs.File, err error) {
defer func() {
if e := recover(); e != nil {
f = nil
// 在 log 中记录当前调用栈
err = fmt.Errorf("gitfs panic: %v\n%s, e, debug.Stack())
}
}()
//....
}