strconvを優先する

プリミティブを文字列に変換したり、逆に文字列をプリミティブに変換する際には、strconvfmtよりも速いです。

非推奨:

for i := 0; i < b.N; i++ {
  s := fmt.Sprint(rand.Int())
}

推奨:

for i := 0; i < b.N; i++ {
  s := strconv.Itoa(rand.Int())
}

文字列をバイトに変換するのを避ける

固定の文字列から繰り返しバイトスライスを作成することは避けるべきです。代わりに、一度変換を行い、その結果をキャプチャします。

非推奨:

for i := 0; i < b.N; i++ {
  w.Write([]byte("Hello world"))
}

推奨:

data := []byte("Hello world")
for i := 0; i < b.N; i++ {
  w.Write(data)
}

コンテナキャパシティを指定する

要素の追加時にコピーとコンテナのリサイズによる後続の割り当てを最小限に抑えるために、可能であればコンテナのキャパシティを指定します。

Mapのキャパシティヒント

ほとんどの場合、make()を使用して初期化する際にキャパシティ情報を提供してください。

make(map[T1]T2, hint)

make()にキャパシティヒントを指定すると、要素の追加時のメモリ再割り当てを減らすために初期化時にマップのサイズを変更しようとします。

スライスとは異なり、マップのキャパシティヒントは完全な事前割り当てを保証しないため、マップに要素を追加する際にはまだ割り当てが発生する可能性があります。

非推奨:

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

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

// mはサイズヒントなしで作成されています。実行時に追加の割り当てが発生するかもしれません。

推奨:

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

m := make(map[string]os.FileInfo, len(files))
for _, f := range files {
    m[f.Name()] = f
}

// mはサイズヒント付きで作成されています。実行時に追加の割り当てが少なくなる可能性があります。

スライスのキャパシティを指定する

ほとんどの場合、特にスライスに要素を追加する場合は、make()を使用して初期化する際にキャパシティ情報を提供します。

make([]T, length, capacity)

マップとは異なり、スライスのキャパシティは単なるヒントではありません。make()で提供されたスライスのキャパシティに十分なメモリを割り当てるため、その後のappend()操作による割り当てはゼロになります(スライスの長さがキャパシティに一致するまで、後続の追加によってリサイズが発生する可能性があります)。

非推奨:

for n := 0; n < b.N; n++ {
  data := make([]int, 0)
  for k := 0; k < size; k++{
    data = append(data, k)
  }
}

推奨:

for n := 0; n < b.N; n++ {
  data := make([]int, 0, size)
  for k := 0; k < size; k++{
    data = append(data, k)
  }
}