性能

  • 不要省略 defer
    • 在大多数情况下 200ns 加速可以忽略不计
  • 总是关闭 http body defer r.Body.Close()
    • 除非你需要泄露 goroutine
  • 过滤但不分配新内存
  1. b := a[:0]
  2. for _, x := range a {
  3. if f(x) {
  4. b = append(b, x)
  5. }
  6. }

为了帮助编译器删除绑定检查,请参见此模式 _ = b [7]

  • time.Time 有指针字段 time.Location 并且这对 go GC 不好
    • 只有使用了大量的 time.Time 才(对性能)有意义,否则用 timestamp 代替
  • regexp.MustCompileregexp.Compile 更好
    • 在大多数情况下,你的正则表达式是不可变的,所以你最好在 func init 中初始化它
  • 请勿在你的热点代码中过度使用 fmt.Sprintf. 由于维护接口的缓冲池和动态调度,它是很昂贵的。
    • 如果你正在使用 fmt.Sprintf("%s%s", var1, var2), 考虑使用简单的字符串连接。
    • 如果你正在使用 fmt.Sprintf("%x", var), 考虑使用 hex.EncodeToString or strconv.FormatInt(var, 16)
  • 如果你不需要用它,可以考虑丢弃它,例如io.Copy(ioutil.Discard, resp.Body)
    • HTTP 客户端的传输不会重用连接,直到body被读完和关闭。
  1. res, _ := client.Do(req)
  2. io.Copy(ioutil.Discard, res.Body)
  3. defer res.Body.Close()
  • 不要在循环中使用 defer,否则会导致内存泄露
    • 因为这些 defer 会不断地填满你的栈(内存)
  • 不要忘记停止 ticker, 除非你需要泄露 channel
  1. ticker := time.NewTicker(1 * time.Second)
  2. defer ticker.Stop()
  1. func (entry Entry) MarshalJSON() ([]byte, error) {
  2. buffer := bytes.NewBufferString("{")
  3. first := true
  4. for key, value := range entry {
  5. jsonValue, err := json.Marshal(value)
  6. if err != nil {
  7. return nil, err
  8. }
  9. if !first {
  10. buffer.WriteString(",")
  11. }
  12. first = false
  13. buffer.WriteString(key + ":" + string(jsonValue))
  14. }
  15. buffer.WriteString("}")
  16. return buffer.Bytes(), nil
  17. }
  1. // noescape hides a pointer from escape analysis. noescape is
  2. // the identity function but escape analysis doesn't think the
  3. // output depends on the input. noescape is inlined and currently
  4. // compiles down to zero instructions.
  5. //go:nosplit
  6. func noescape(p unsafe.Pointer) unsafe.Pointer {
  7. x := uintptr(p)
  8. return unsafe.Pointer(x ^ 0)
  9. }
  • 对于最快的原子交换,你可以使用这个 m := (*map[int]int)(atomic.LoadPointer(&ptr))
  • 如果执行许多顺序读取或写入操作,请使用缓冲 I/O

    • 减少系统调用次数
  • 有 2 种方法清空一个 map:

    • 重用 map 内存 (但是也要注意 m 的回收)
  1. for k := range m {
  2. delete(m, k)
  3. }
  • 分配新的
  1. m = make(map[int]int)