高质量编程与性能调优实战—第一部分|青训营笔记

55 阅读3分钟

高质量编程与性能调优实战—第一部分|青训营笔记

什么是高质量——编写的代码能够达到正确可靠、简洁清晰的目标可称之为高质量代码

  • 各种边界条件是否考虑完备
  • 异常情况处理,稳定性保证
  • 易读易维护

编程原则

  • 简单性
  • 可读性
  • 生产力

编码规范

  • 代码格式

    • 推荐使用 Gofmt 自动格式化代码。
    • Gofmt:Go 语言官方提供的工具,能自动格式化 Go 语言代码为官方统一风格,常见 IDE 都支持方便的配置。
    • Goimports:也是 Go 语言官方提供的工具,实际等于 Gofmt 加上依赖包管理,自动增删依赖的包引用、将依赖包按字母序排序并分类。
  • 注释

    • 注释应该解释代码作用。
    • 注释应该解释代码如何做的。
    • 注释应该解释代码实现的原因。
    • 注释应该解释代码什么情况会出错。
  • 命名规范

    • 变量的命名:简洁胜于冗长。缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写。变量距离其被使用的地方越远,需要携带的信息就需要越多。
    • 函数的命名:函数名不必携带包名的上下文信息。函数名需要尽可能地简短。当函数返回类型与包名相同时,可以省略类型信息。
    • 包的命名:包名仅由小写字母组成。包名简短且包含一定的上下文信息。不要与标准库问名。

控制流程

  • 线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支。如果两个分支中都包含return语句,则可以去除冗余的else。

    // Bad
    if foo {
    	return X
    } else {
    	return nil
    }
    // Good
    if foo {
    	return X
    }
    return nil
    
  • 尽量保持正常代码路径为最小缩进 优先处理错误情况特殊情况,尽早返回或继续循环来减少嵌套

    // Bad
    func OneFunc( ) error {
    	err := doSomething( )
    	if err == nil{
    		err := doAnotherThing( )
    		if err == nil{
    		return nil // normal case
    	}
    		return err
    	}
    	return err
    }
    
    
    // Good
    func OneFunc( ) error {
    	if err := doSomething(); err != nil {
    		return err
    	}
    	if err. := doAnotherThing(); err != nil {
    		return err
    	}
    	returrpnil // normal case
    }
    
  • 正常流程代码沿着屏幕向下移动。

  • 提升代码可维护性和可读性。

  • 故障问题大多出现在复杂的条件语句和循环语句中。

错误和异常处理

  • 简单错误

    1. 简单的错误指的是仅出现一次的错误, 且在其他地方不需要捕获该错误
    2. 优先使用errors.New来创建匿名变量来直接表示简单错误
    3. 如果有格式化的需求,使用fmt.Errorf
  • 错误的Wrap和Unwrap

    • 错误的Wrap实际上是提供了一个error嵌套另一个error的能力,从而生成一个error的跟踪链
    • fmt.Errorf中使用: %w关键字来将一个错误关联至错误链中
  • 错误判定

    • 判定一个错误是否为特定错误,使用errors.Is

    • 不同于使用==,使用该方法可以判定错误链.上的所有错误是否含有特定的错误

      data, err = lockedfile. Read( targl2209
      	if errors.Is(err, fs.ErrNotExist) {
      		// Treat non-existent as empty,to bootstrap the "latest" file
      		// the first time we connect to a given database.
      		return []byte{}, nil
      	}
      return data, err
      
    • 在错误链上获取特定种类的错误,使用errors.As

      if _,err := os.0pen( "non-existing"); err != nil {
      	var pathError *fs. PathEr r
      		if errors.As(err, &pathEroor) {
      		fmt. Println("Failed at path:", pathError .Path)
      	} else {
      		fmt.Println(err)
      	}
      }
      
  • panic

    1. 不建议在业务代码中使用panic
    2. 调用函数不包含recover会造成程序崩溃
    3. 若问题可以被屏蔽或解决,建议使用error代替panic
    4. 当程序启动阶段发生不可逆转的错误时,可以在init或main函数中使用panic
  • recover

    1. recover只能在被defer的函数中使用
    2. 嵌套无法生效
    3. 只在当前goroutine生效
    4. defer的语句是后进先出