Go高质量编程 |青训营笔记

100 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记

我讲从以下几个方面:高质量编程 性能优化

高质量编程

  1. 原则:间接性 可读性 生产力(团队合作效率)
  2. 规范
    • 代码格式:gofmt
    • 注释:代码作用、代码如何做、实现原因、代码限制条件、公共符号一定要注释
    • 命名:根据需要的信息量、大小写、缩写
  3. 控制流程:实现最小缩进
  4. 错误和异常处理:
    • 简单错误 errors.New
    • 复杂错误 fmt.Errorf
    • 错误判定 errors.As
    • panic(少用)
    • recover(当前goroutine被defer函数中生效)
func defaultCheckRedirect(req *Request, via []*Request) error{
        if len(via) >= 10{
            return errors.New("stopped after 10 redirects")
        }
        return nil
}
list, _, err := c.GetBytes(cache.Subkey(a.actionID, "srcfiles"))
if err != nil{
    return fmt.Errorf("reading srcfiles list: %w", err)
}

性能优化

  1. 工具: benchmark go test -bench=. -benchmem
    • 函数名 被执行次数 每次执行时间 执行申请内存大小 每次执行申请内存次数
  2. 建议:
    • Slice 和 Map 预分配

    • 字符串拼接:使用strings.Builder >(内存)> bytes.Buffer > (重新内存分配)"+"

      2.1. +法:右边的值会引起内存分配

      2.2. Bytes.Buffer: bytes包处理方式是再次进行一次切片处理

      2.3. Strings.Builder: Strings包是直接指针转换

      举例说明:

     s := "aa"
     for i:=0; i<size; i++{
         s +="ccc"
     }
    var s bytes.Buffer
    for i:=0; i<10; i++{
        s.WriteString("cc")
    }
    s.String();
     var s strings.Builder
     for i:=0; i<size; i++{
         s.WriteString("cc")
     }
     s.String()
  • 使用空结构体struct{} 不占用空间-是作为map实现set的不错的工具(这里面我们只需要用map键,而非它的值) 如果用map的值设为了bool也会多占用1个字节空间。因此强推使用空结构体,省空间

  • atomic包 下面我们比较atomic保护变量的并发安全和sync.Mutex保护的并发安全效果 使用atomic包示例;

    type atomicCounter struct{
        i int32
    }
    
    func AtomicAddOne(c*atomicCounter){
        atomic.AddInt32(&c.i,1)
    }
    type mutexCounter struct{
        i int32
        m sync.Mutex
    }
    
    func MutexAddOne(c *mutexCounter){
        c.m.Lock()
        c.i++
        c.m.Unlock()
    }

结果:

{076F9070-3E82-AAD1-317D-89793684B15A}.jpg