高质量编程简介和代码规范

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

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

编程原则:

  • 简单性
    • 消除”多余的复杂性“,以简单清晰的逻辑编写代码
    • ’不理解的代码无法修复改进
  • 可读性
    • 代码是写给人看的,而不是机器
    • 编写可维护的代码的第一步是确保代码可读
  • 生产力
    • 团队整体的工作效率非常重要

编码规范:

  • 代码格式尽可能地统一

    • 推荐使用gofmt自动格式化代码
  • 注释(好的代码有很多注释,不好的代码需要很多注释,应该提供一些使用该代码的上下文信息

    • 注释应该做的:
      1. 注释应该注释的内容
      2. 注释应该解释的代码,它是如何做的
      3. 注释应该解释代码实现的原因,适当解释代码的外部因素,提供额外的上下文
      4. 注释应该解释代码什么情况下可能会出错,解释代码的限制条件
    • 公共符号始终要进行注释
      1. 包中声明的每个公共的符号:变量,常量,函数,以及结构都需要进行注释
      2. 任何及不明显也不简短的公共功能必须予以注释
      3. 无论长度或者复杂程度如何,对库中的任何函数进行注释
      4. 有一个例外,不需要注释实现接口的方法
  • 命名规范(核心目标是降低阅读代码的成本,重点考虑上下文的信息)

    • 简洁胜于冗长
    • 缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写
      1. 利用ServeHTTP而不是ServeHttp
      2. 使用XMLHTTPResquest或者xmlHTTPRequest
    • 变量距离其被使用的地方越远,则需要携带更多的上下文信息,参数名是可以代表着一些特点含义,知道它的意思
    • 函数名:
      1. 函数名不携带包名的上下文信息,因为包名和函数名总是成对出现的
      2. 函数名尽量简短
      3. 当名为foo的包某个函数返回类型Foo时,可以省略类型信息而不导致歧义
      4. 当名为foo的包某个函数返回类型T时,可以在函数中加入类型信息
    • 包名:
      1. 只由小写字母组成。不含有大写字母或者下划线等
      2. 简短并且包含一定的上下文信息
      3. 不要与标准库重名
  • 控制流程

    • 避免嵌套,保持正常流程

    • 尽量保持正常代码路径为最小缩进。优先处理错误情况或者特殊情况,尽早返回

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

      // Bad
      func OneFunc() error{
              
              
      	err:= doSomething()
      	if err == nil{
              
              
      		err := doAnoterThing()
      		if err == nil{
              
              
      			return nil
      		}
      		return err
      	}
      	return err	
      }
      // 进行改进
      func OneFunc() error{
              
              
          if err := doSomething(); err != nil{
              
              
              return err
          }
          if err := doAnotherthing(); err != nil{
              
              
              return err
          }
          return
      }
      
  • 错误和异常处理

    • 简单的错误指仅出现一次的错误,其在其它的地方不需要捕获该错误

    • 优先使用errors.New来创建匿名变量来直接表示简单错误

    • 如果由格式化的需求,使用fmt.Errof

      func defaultCheckRedirect(req *Request, via []*Request) error {
              
              
      	if len(via) >= 10 {
              
              
      		return errors.New("stopped after 10 redirects")
      	}
      	return nil
      }
      
    • 错误的Wrap和Unwrap

      1. 错误的wrap实际上是提供了一个error嵌套另一个error的能力,从而生成error的跟踪链

      2. 在fmt.Errorf中使用:%w关键字来将一个错误关联到另一个错误上去

        list, _, err := c.GEtBytes(cache.Subkey(a.actionID,"srcfiles"))
        if err != nil{
                  
                  
            return fmt.Errorf("reading srcfiles list: w%",err)
        }
        
    • 判断一个错误是否为指定的错误,使用errors.Is,不同于==,该方法可以判断错误链上是否含有该错误

      if errors.Is(err,fs.ErrNotExist){
              
              
          return true,nil
      }
      
    • 在错误链上获取特定种类的错误,使用errors.As

      if errors.As(err,fs.pathError)
      
    • panic

      1. 业务中不建议使用你panic,如果出现说明业务基本崩溃了,用于真正的异常
      2. 若有问题可以被屏蔽或者解决,建议使用error来代替panic
      3. 调用时不使用recover会让程序奔溃
    • recover

      1. recover只能在defer的函数中使用
      2. 嵌套无法失效
      3. 只能在gotuntine中被defer的函数生效
      4. defer语句会在函数返回前被调用,多个defer语句是后进先出的

猜你喜欢

转载自blog.csdn.net/weixin_68798281/article/details/131997041