uber go code 規範(性能)

前言

從接觸 Golang 到現在, 感覺到的很深的一點是, go 的代碼無論是大佬還是菜鳥寫出的代碼, 都有着大體統一的 格式/流程, 這也是 Go 被開發者喜愛的一個原因, 但是還有一些, 比如變量的命名方式等, 可以稱之爲 風格 的東西, 卻不盡相同, 我在開發中, 其實也希望有一個相對權威的指導意見, 後來就找到了 uber 團隊出品的開發規範.
uber 是衆多公司中, 比較早使用 go 語言的了, 其本身也開源了一些優質的模塊, 有機會的話希望也能向大家展示一下, 而在 uber 內部開發中, 經過持續的迭代, 開源了自己的代碼規範, 這裏給大家解讀一下
需要特別指出的是, 下面的內容並不是一定需要遵守, 這裏你可以選擇自己認爲正確的可行的規範.
團隊內使用統一的風格, 可以提高代碼的可讀性
本篇記錄性能部分, 旨在特定情況下提高程序的性能

優先使用 strconv 而不是 fmt

將 int 轉換成 string 時, 使用 strconv 的方法比 fmt 的速度更快
錯誤的

package main

import (
	"fmt"
	"strconv"
	"time"
)

func main() {
	start := time.Now()
	for i := 0; i < 10000; i++ {
		fmt.Sprintln(i)
	}
	fmt.Println(time.Now().Sub(start))
}

查看耗時

➜  test go run main.go
872.779µs

正確的

package main

import (
	"fmt"
	"strconv"
	"time"
)

func main() {
	start := time.Now()
	for i := 0; i < 10000; i++ {
		strconv.Itoa(i)
	}
	fmt.Println(time.Now().Sub(start))
}

查看耗時

➜  test go run main.go
233.211µs

避免字符串轉換成字節

不要頻繁的從固定字符串轉換成字節, 而是隻創建一次並將結果保存, 反覆使用
錯誤的

package main

import (
	"fmt"
	"time"
)

func main() {
	start := time.Now()
	for i := 0; i < b.N; i++ {
		 w.Write([]byte("Hello world"))
	}
	fmt.Println(time.Now().Sub(start))
}

正確的

package main

import (
	"fmt"
	"time"
)

func main() {
	start := time.Now()
	data := []byte("Hello world")
	for i := 0; i < b.N; i++ {
	  w.Write(data)
	}
	fmt.Println(time.Now().Sub(start))
}

初始化 Map 和切片時預估長度

在初始化 map 和切片時, 就指定其長度, 防止 go 進行動態擴容

map

使用 make 進行初始化時提供容量信息

make(map[T]T, len)

這可能會減少動態擴容的次數, 因爲 go 的 map 容量不是一定準確判斷, 所以只是可能減少
錯誤的

m := make(map[string]os.FileInfo)

files, _ := ioutil.ReadDir("./files")
for _, f := range files {
    m[f.Name()] = f
}

正確的


files, _ := ioutil.ReadDir("./files")

m := make(map[string]os.FileInfo, len(files))  // 直接指定長度
for _, f := range files {
    m[f.Name()] = f
}

指定切片容量

在創建切片時, 儘可能的提供容量信息

make([]T, length, capacity)

go 對切片的處理, 當切片長度夠用時, 一定不會出現分配操作, 節省時間
錯誤的

for n := 0; n < b.N; n++ {
  data := make([]int, 0)  // 長度爲0
  for k := 0; k < size; k++{
    data = append(data, k)  // 長度不夠時進行擴容
  }
}

正確的

for n := 0; n < b.N; n++ {
  data := make([]int, 0, size)  // 指定 size
  for k := 0; k < size; k++{
    data = append(data, k)  // 永遠不會擴容
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章