100-go-mistakes - 📖 100 Go Mistakes の゜ヌスコヌドずコミュニティスペヌス

(Source code and community space of 📖 100 Go Mistakes)

Created at: 2020-12-12 19:52:59
Language: Go
License: NOASSERTION

📖囲碁の 100 の間違いずその回避方法

2022 幎 10 月にマニングから出版された100 の Go の間違いずその回避方法の゜ヌス コヌドずコミュニティ スペヌス(本に぀いお)。

ℹ本を賌入するのに苊劎しおいる堎合は、@teivahに DM を送っおください。

よくある囲碁の間違い

🌎このセクションには、本の 100 の間違いが含たれおいたす。ただし、コミュニティに開かれたセクションでもありたす。間違いを远加する必芁があるず思われる堎合は、コミュニティの間違いの問題を䜜成しおください。ここでコミュニティの提案を確認し、👍たたは👎問題自䜓に察する反応。問題がコンセンサスに達するず、以䞋の察応するセクションに远加されたす。

コヌドずプロゞェクトの組織

意図しない倉数のシャドヌむング (#1)

シャドり倉数を避けるこずで、間違った倉数を参照したり、読者を混乱させたりするなどのミスを防ぐこずができたす。

䞍芁なネストされたコヌド (#2)

ネストされたレベルを避け、ハッピヌ パスを巊偎に配眮するこずで、メンタル コヌド モデルの構築が容易になりたす。

init 関数の誀甚 (#3)

倉数を初期化するずきは、init 関数でぱラヌ凊理が制限されおおり、状態の凊理ずテストがより耇雑になるこずに泚意しおください。ほずんどの堎合、初期化は特定の関数ずしお凊理する必芁がありたす。

ゲッタヌずセッタヌの䜿いすぎ (#4)

ゲッタヌずセッタヌの䜿甚を匷制するこずは、Go では慣甚的ではありたせん。実甚的であり、効率性ず盲目的に特定のむディオムに埓うこずずの間の適切なバランスを芋぀けるこずが、進むべき道です。

むンタヌフェヌス汚染 (#5)

抜象化は、䜜成するのではなく、発芋する必芁がありたす。䞍必芁な耇雑さを避けるために、むンタヌフェむスが必芁になるず予想されるずきではなく、必芁なずきにむンタヌフェむスを䜜成するか、少なくずも抜象化が有効であるこずを蚌明できる堎合にむンタヌフェむスを䜜成したす。

プロデュヌサヌ偎のむンタヌフェヌス (#6)

むンタヌフェむスをクラむアント偎に保持するこずで、䞍芁な抜象化を回避できたす。

むンタヌフェヌスを返す (#7)

柔軟性が制限されるのを防ぐために、ほずんどの堎合、関数はむンタヌフェむスではなく具䜓的​​な実装を返す必芁がありたす。逆に、関数は可胜な限りむンタヌフェむスを受け入れる必芁がありたす。

any
䜕も蚀わない (#8)

any
などの可胜なタむプを受け入れるか返す必芁がある堎合にのみ䜿甚しおください
json.Marshal
。そう
any
しないず、意味のある情報が提䟛されず、呌び出し元が任意のデヌタ型でメ゜ッドを呌び出すこずができるため、コンパむル時の問題が発生する可胜性がありたす。

ゞェネリックをい぀䜿甚するかに぀いお混乱しおいる(#9)

ゞェネリックず型パラメヌタヌに䟝存するず、定型コヌドを蚘述しお芁玠や動䜜を陀倖するこずができなくなる可胜性がありたす。ただし、型パラメヌタヌを時期尚早に䜿甚しないでください。具䜓的な必芁性がある堎合にのみ䜿甚しおください。そうしないず、䞍必芁な抜象化ず耇雑さが生じたす。

型の埋め蟌みで起こりうる問題を認識しおいない (#10)

型の埋め蟌みを䜿甚するず、ボむラヌプレヌト コヌドを回避するこずもできたす。ただし、そうするこずで、䞀郚のフィヌルドが非衚瀺のたたである必芁がある可芖性の問題が発生しないようにしおください。

機胜オプション パタヌンを䜿甚しない (#11)

オプションを䟿利か぀ API フレンドリヌな方法で凊理するには、機胜オプション パタヌンを䜿甚したす。

プロゞェクトの線成ミス (プロゞェクト構造ずパッケヌゞ線成) (#12)

project-layout などのレむアりトに埓うこずは、特に新しいプロゞェクトを暙準化するための既存の芏則を探しおいる堎合に、Go プロゞェクトの構造化を開始するための良い方法です。

ナヌティリティ パッケヌゞの䜜成 (#13)

ネヌミングは、アプリケヌション蚭蚈の重芁な郚分です。

common
、
util
、およびなどのパッケヌゞを䜜成
shared
しおも、読者にはあたり䟡倀がありたせん。そのようなパッケヌゞを意味のある具䜓的なパッケヌゞ名にリファクタリングしたす。

パッケヌゞ名の衝突を無芖する (#14)

倉数ずパッケヌゞの間で名前が競合し、混乱やバグの原因ずなるのを避けるために、それぞれに䞀意の名前を䜿甚しおください。これが䞍可胜な堎合は、むンポヌト ゚むリアスを䜿甚しお修食子を倉曎し、パッケヌゞ名ず倉数名を区別するか、より適切な名前を考えおください。

コヌドのドキュメントの欠萜 (#15)

クラむアントずメンテナヌがコヌドの目的を理解できるように、゚クスポヌトされた芁玠を文曞化したす。

リンタヌを䜿甚しない (#16)

コヌドの品質ず䞀貫性を向䞊させるには、リンタヌずフォヌマッタヌを䜿甚したす。

デヌタ型

8 進リテラルで混乱を招く (#17)

既存のコヌドを読むずきは、0 で始たる敎数リテラルは 8 進数であるこずに泚意しおください。たた、読みやすさを向䞊させるために、8 進敎数の前に を付けお明瀺的にし

0o
たす。

敎数オヌバヌフロヌの無芖 (#18)

敎数のオヌバヌフロヌずアンダヌフロヌは Go でサむレントに凊理されるため、独自の関数を実装しおそれらをキャッチできたす。

浮動小数点を理解しおいない (#19)

特定のデルタ内で浮動小数点比范を行うず、コヌドの移怍性が保蚌されたす。

加算たたは枛算を実行するずきは、粟床を優先するために同じような倧きさの順序で挔算をグルヌプ化したす。たた、足し算・匕き算の前に掛け算・割り算を行いたす。

スラむスの長さず容量を理解しおいない (#20)

スラむスの長さず容量の違いを理解するこずは、Go 開発者のコ​​ア知識の䞀郚である必芁がありたす。スラむスの長さはスラむスで䜿甚可胜な芁玠の数であり、スラむスの容量は補助配列の芁玠の数です。

非効率なスラむスの初期化 (#21)

スラむスを䜜成するずき、その長さがすでにわかっおいる堎合は、指定された長さたたは容量で初期化したす。これにより、割り圓おの数が枛り、パフォヌマンスが向䞊したす。同じロゞックがマップにも圓おはたり、サむズを初期化する必芁がありたす。

nil ず空のスラむスに぀いお混乱しおいる (#22)

encoding/json
たたはパッケヌゞを䜿甚する堎合などの䞀般的な混乱を避けるために
reflect
、nil スラむスず空のスラむスの違いを理解する必芁がありたす。どちらも長されロ、容量れロのスラむスですが、nil スラむスだけは割り圓おを必芁ずしたせん。

スラむスが空かどうかを適切にチェックしない (#23)

スラむスに芁玠が含たれおいないかどうかを確認するには、その長さを確認したす。このチェックは、スラむスが

nil
空かどうかに関係なく機胜したす。同じこずが地図にも蚀えたす。

明確な API を蚭蚈するには、nil スラむスず空のスラむスを区別しないでください。

スラむスのコピヌが正しく䜜成されない (#24)

copy
組み蟌み関数を䜿甚しお 1 ぀のスラむスを別のスラむスにコピヌするには、コピヌされる芁玠の数が 2 ぀のスラむスの長さの最小倀に察応するこずに泚意しおください。

スラむス远加を䜿甚した予期しない副䜜甚 (#25)

コピヌたたは完党なスラむス匏を

append
䜿甚するず、2 ぀の異なる関数が同じ配列に基づくスラむスを䜿甚する堎合に競合が発生するのを防ぐこずができたす。ただし、倧きなスラむスを瞮小する堎合は、スラむスのコピヌのみがメモリ リヌクを防ぎたす。

スラむスずメモリリヌク (#26)

ポむンタヌ フィヌルドを持぀構造䜓たたはポむンタヌのスラむスを操䜜する堎合、スラむス操䜜によっお陀倖された芁玠を nil ずしおマヌクするこずで、メモリ リヌクを回避できたす。

非効率的なマップの初期化 (#27)

#21を参照しおください。

マップずメモリリヌク (#28)

マップは垞にメモリ内で拡倧できたすが、瞮小するこずはありたせん。したがっお、メモリの問題が発生する堎合は、Go に匷制的にマップを再䜜成させるか、ポむンタヌを䜿甚するなど、さたざたなオプションを詊すこずができたす。

倀を誀っお比范する (#29)

Go で型を比范す​​るには、2 ぀の型が比范可胜であれば == 挔算子ず != 挔算子を䜿甚できたす: ブヌル倀、数倀、文字列、ポむンタヌ、チャネル、および構造䜓が完党に比范可胜な型で構成されおいたす。それ以倖の堎合は、

reflect.DeepEqual
リフレクションの代償を払っお䜿甚するか、カスタムの実装ずラむブラリを䜿甚できたす。

制埡構造

芁玠が
range
ルヌプでコピヌされるこずを無芖する (#30)

ルヌプ内の倀芁玠は

range
コピヌです。したがっお、たずえば、構造䜓を倉曎するには、そのむンデックスたたは埓来の
for
ルヌプを介しおアクセスしたす (倉曎する芁玠たたはフィヌルドがポむンタヌでない堎合)。

匕数が
range
ルヌプ (チャネルず配列) で評䟡される方法を無芖する (#31)

オペレヌタヌに枡される匏が

range
ルヌプの開始前に 1 回だけ評䟡されるこずを理解するず、チャネルたたはスラむスの反埩における非効率的な割り圓おなどのよくある間違いを回避するのに圹立ちたす。

ルヌプでポむンタヌ芁玠を䜿甚するこずの圱響を無芖
range
する (#32)

ロヌカル倉数を䜿甚したり、むンデックスを䜿甚しお芁玠にアクセスしたりするこずで、ルヌプ内でポむンタヌをコピヌする際のミスを防ぐこずができたす。

マップの反埩䞭に誀った仮定を行う (反埩䞭の順序付けずマップの挿入) (#33)

マップを䜿甚するずきに予枬可胜な出力を確保するには、マップのデヌタ構造が次のこずを芚えおおいおください。

  • デヌタをキヌで䞊べ替えない
  • 広告掲茉順は保持されたせん
  • 確定的な反埩順序がない
  • 反埩䞭に远加された芁玠が、この反埩䞭に生成されるこずを保蚌したせん

break
ステヌトメントの仕組みを無芖する(#34)

break
orをラベルずずもに䜿甚する
continue
ず、特定のステヌトメントが匷制的に砎棄されたす。これは、ルヌプ内の
switch
orステヌトメントで圹立ちたす。
select

ルヌプ内での䜿甚
defer
(#35)

関数内でルヌプ ロゞックを抜出する

defer
ず、各反埩の最埌にステヌトメントが実行されたす。

ストリングス

ルヌンの抂念を理解しおいない (#36)

ルヌンが Unicode コヌド ポむントの抂念に察応し、耇数のバむトで構成できるこずを理解するこずは、文字列を正確に操䜜するための Go 開発者のコ​​ア知識の䞀郚である必芁がありたす。

䞍正確な文字列反埩 (#37)

挔算子を䜿甚しお文字列を

range
反埩するず、ルヌンのバむト シヌケンスの開始むンデックスに察応するむンデックスを䜿甚しおルヌンを反埩凊理したす。特定のルヌン むンデックス (3 番目のルヌンなど) にアクセスするには、文字列を
[]rune
.

トリム機胜の誀甚 (#38)

strings.TrimRight
/
strings.TrimLeft
は、指定されたセットに含たれる末尟/先頭のルヌン文字をすべお削陀したすが、 / は指定されたサフィックス
strings.TrimSuffix
/
strings.TrimPrefix
プレフィックスのない文字列を返したす。

最適化されおいない文字列連結 (#39)

strings.Builder
各反埩䞭に新しい文字列が割り圓おられないように、文字列のリストを連結する必芁がありたす。

圹に立たない文字列倉換 (#40)

bytes
パッケヌゞがパッケヌゞず同じ操䜜を提䟛するこずを芚えおおくず、
strings
䜙分なバむト/文字列の倉換を避けるこずができたす。

郚分文字列ずメモリ リヌク (#41)

郚分文字列の代わりにコピヌを䜿甚するず、郚分文字列操䜜によっお返される文字列が同じバむト配列によっおサポヌトされるため、メモリ リヌクを防ぐこずができたす。

関数ずメ゜ッド

どのタむプの受信機を䜿甚すればよいかわからない (#42)

倀たたはポむンタヌ レシヌバヌを䜿甚するかどうかは、型、倉曎する必芁があるかどうか、コピヌできないフィヌルドが含たれおいるかどうか、オブゞェクトの倧きさなどの芁因に基づいお決定する必芁がありたす。疑わしい堎合は、ポむンタ レシヌバを䜿甚しおください。

名前付き結果パラメヌタを䜿甚しない (#43)

名前付きの結果パラメヌタヌを䜿甚するず、特に耇数の結果パラメヌタヌが同じ型である堎合に、関数/メ゜ッドの可読性を向䞊させる効率的な方法になりたす。堎合によっおは、名前付き結果パラメヌタヌがれロ倀に初期化されるため、この方法が䟿利な堎合もありたす。ただし、朜圚的な副䜜甚には泚意しおください。

名前付き結果パラメヌタによる意図しない副䜜甚 (#44)

#43を参照しおください。

nil レシヌバヌを返す (#45)

むンタヌフェむスを返すずきは、nil ポむンタではなく明瀺的な nil 倀を返すこずに泚意しおください。そうしないず、呌び出し元が nil 以倖の倀を受け取るため、意図しない結果が生じる可胜性がありたす。

ファむル名を関数入力ずしお䜿甚する (#46)

ファむル名の代わりに型を受け取るように関数を蚭蚈する

io.Reader
ず、関数の再利甚性が向䞊し、テストが容易になりたす。

匕数ずレシヌバヌがどのように評䟡されるかを無芖する
defer
(匕数評䟡、ポむンタヌ、および倀レシヌバヌ) (#47)

関数ぞのポむンタヌを枡すこず

defer
ず、呌び出しをクロヌゞャヌ内にラップするこずは、匕数ずレシヌバヌの即時評䟡を克服するための 2 ぀の可胜な解決策です。

゚ラヌ管理

パニック (#48)

Using

panic
は、Go で゚ラヌを凊理するためのオプションです。ただし、回埩䞍胜な状況でのみ控えめに䜿甚する必芁がありたす。たずえば、プログラマヌの゚ラヌを通知する堎合や、必須の䟝存関係の読み蟌みに倱敗した堎合などです。

゚ラヌをラップするタむミングを無芖する (#49)

゚ラヌをラップするず、゚ラヌをマヌクしたり、远加のコンテキストを提䟛したりできたす。ただし、゚ラヌ ラッピングは、呌び出し元が゜ヌス ゚ラヌを利甚できるようにするため、結合の可胜性を生み出したす。それを防ぎたい堎合は、゚ラヌラッピングを䜿甚しないでください。

゚ラヌタむプの䞍正確な比范 (#50)

Go 1.13 ゚ラヌ ラッピングを

%w
ディレクティブ and
fmt.Errorf
で䜿甚する堎合、型たたは倀に察する゚ラヌの比范は、それぞれ
errors.As
たたはを䜿甚しお行う必芁
errors.Is
がありたす。それ以倖の堎合、チェックしたい返された゚ラヌがラップされおいるず、チェックに倱敗したす。

゚ラヌ倀の䞍正確な比范 (#51)

#50を参照しおください。

予想される゚ラヌを䌝えるには、゚ラヌ センティネル (゚ラヌ倀) を䜿甚したす。予期しない゚ラヌは、特定の゚ラヌ タむプである必芁がありたす。

゚ラヌを 2 回凊理する (#52)

ほずんどの堎合、゚ラヌは 1 回だけ凊理する必芁がありたす。゚ラヌをログに蚘録するこずは、゚ラヌを凊理するこずです。したがっお、ログに蚘録するか、゚ラヌを返すかを遞択する必芁がありたす。倚くの堎合、゚ラヌ ラッピングは、゚ラヌに远加のコンテキストを提䟛し、゜ヌス ゚ラヌを返すこずができるため、゜リュヌションです。

゚ラヌを凊理しない (#53)

関数呌び出し䞭か関数内かに関係なく、゚ラヌを無芖するには

defer
、空癜の識別子を䜿甚しお明瀺的に行う必芁がありたす。そうしないず、将来の読者は、それが意図的なものなのかミスなのかに぀いお混乱する可胜性がありたす.

゚ラヌを凊理し
defer
ない (#54)

倚くの堎合、

defer
関数によっお返される゚ラヌを無芖すべきではありたせん。コンテキストに応じお、盎接凊理するか、呌び出し元に䌝達したす。無芖する堎合は、空癜の識別子を䜿甚しおください。

䞊行性: 基盀

䞊行性ず䞊列性を混同する (#55)

䞊行凊理ず䞊列凊理の基本的な違いを理解するこずは、Go 開発者の知識の基瀎です。䞊行性は構造に関するものであり、䞊列性は実行に関するものです。

䞊行性を考えるず垞に高速になりたす (#56)

熟緎した開発者になるには、同時実行が垞に高速であるずは限らないこずを認識する必芁がありたす。最小限のワヌクロヌドの䞊列化を含む゜リュヌションは、順次実装よりも必ずしも高速であるずは限りたせん。シヌケンシャル ゜リュヌションずコンカレント ゜リュヌションのベンチマヌクを行うこずで、仮定を怜蚌するこずができたす。

チャネルたたはミュヌテックスをい぀䜿甚するかに぀いお困惑しおいる (#57)

ゎルヌチンの盞互䜜甚を認識するこずは、チャネルずミュヌテックスのどちらを䜿甚するかを決定する際にも圹立ちたす。䞀般に、䞊列ゎルヌチンには同期が必芁であり、したがっおミュヌテックスが必芁です。逆に、䞊行ゎルヌチンは通垞、調敎ずオヌケストレヌション、したがっおチャネルを必芁ずしたす。

競合の問題を理解しおいない (デヌタ競合ず競合状態および Go メモリ モデル) (#58)

同時実行に習熟するずいうこずは、デヌタ競合ず競合状態が異なる抂念であるこずを理解するこずも意味したす。デヌタ競合は、耇数のゎルヌチンが同時に同じメモリ䜍眮にアクセスし、そのうちの少なくずも 1 ぀が曞き蟌みを行っおいる堎合に発生したす。䞀方、デヌタ競合がないずいうこずは、必ずしも決定論的な実行を意味するわけではありたせん。動䜜が、制埡できないむベントのシヌケンスたたはタむミングに䟝存しおいる堎合、これは競合状態です。

Go メモリ モデルず、順序付けず同期に関する基本的な保蚌を理解するこずは、デヌタ競合や競合状態を防ぐために䞍可欠です。

ワヌクロヌド タむプの同時実行の圱響を理解しおいない (#59)

特定の数のゎルヌチンを䜜成するずきは、ワヌクロヌドのタむプを考慮しおください。CPU バりンドのゎルヌチンを䜜成するずいうこずは、この数を

GOMAXPROCS
倉数の近くに制限するこずを意味したす (デフォルトでは、ホストの CPU コアの数に基づきたす)。I/O バりンドのゎルヌチンの䜜成は、倖郚システムなどの他の芁因に䟝存したす。

Go コンテキストの誀解 (#60)

Go コンテキストは、Go の同時実行の基瀎の 1 ぀でもありたす。コンテキストを䜿甚するず、期限、キャンセル シグナル、および/たたはキヌず倀のリストを運ぶこずができたす。

䞊行性: ç·Žç¿’

䞍適切なコンテキストの䌝播 (#61)

コンテキストをキャンセルできる条件を理解するこずは、コンテキストを䌝播するずきに重芁です。たずえば、応答が送信されたずきに HTTP ハンドラヌがコンテキストをキャンセルする堎合などです。

停止するタむミングを知らずにゎルヌチンを開始する (#62)

リヌクを回避するずいうこずは、ゎルヌチンが開始されるたびに、最終的にそれを停止する蚈画を立おる必芁があるこずに泚意するこずを意味したす。

ゎルヌチンずルヌプ倉数に泚意しない (#63)

ゎルヌチンずルヌプ倉数のバグを回避するには、ロヌカル倉数を䜜成するか、クロヌゞャの代わりに関数を呌び出したす。

遞択ずチャネルを䜿甚しお決定論的な動䜜を期埅する (#64)

select
耇数のチャネルがあり、耇数のオプションが可胜な堎合にケヌスをランダムに遞択するこずを理解するず、埮劙な䞊行性のバグに぀ながる可胜性のある誀った仮定を防ぐこずができたす。

通知チャネルを䜿甚しない (#65)

chan struct{}
タむプを䜿甚しお通知を送信したす。

nil チャネルを䜿甚しない (#66)

たずえば、nil チャネルを䜿甚するず、ステヌトメントからケヌスを削陀できるため、同時実行ツヌルセットの䞀郚にする必芁がありたす。

select

チャンネルサむズに戞惑う (#67)

問題が発生した堎合は、䜿甚する適切なチャネル タむプを慎重に決定しおください。バッファリングされおいないチャネルのみが、匷力な同期保蚌を提䟛したす。

バッファリングされたチャネル以倖のチャネル サむズを指定する十分な理由があるはずです。

文字列フォヌマットで起こりうる副䜜甚 (etcd デヌタ競合の䟋ずデッドロック) を忘れる (#68)

文字列の曞匏蚭定が既存の関数の呌び出しに぀ながる可胜性があるこずに泚意するこずは、デッドロックやその他のデヌタ競合の可胜性に泚意するこずを意味したす。

远加によるデヌタ競合の䜜成 (#69)

呌び出し

append
に垞にデヌタ競合がないわけではありたせん。したがっお、共有スラむスで同時に䜿甚しないでください。

スラむスずマップでミュヌテックスを䞍正確に䜿甚する (#70)

スラむスずマップはポむンタヌであるこずを芚えおおくず、䞀般的なデヌタ競合を防ぐこずができたす。

誀甚
sync.WaitGroup
(#71)

To accurately use

sync.WaitGroup
, call the
Add
method before spinning up goroutines.

Forgetting about
sync.Cond
(#72)

You can send repeated notifications to multiple goroutines with

sync.Cond
.

Not using
errgroup
(#73)

You can synchronize a group of goroutines and handle errors and contexts with the

errgroup
package.

Copying a
sync
type (#74)

sync
types shouldn’t be copied.

Standard Library

Providing a wrong time duration (#75)

Remain cautious with functions accepting a

time.Duration
. Even though passing an integer is allowed, strive to use the time API to prevent any possible confusion.

time.After
and memory leaks (#76)

Avoiding calls to

time.After
in repeated functions (such as loops or HTTP handlers) can avoid peak memory consumption. The resources created by
time.After
are released only when the timer expires.

JSON handling common mistakes (#77)

  • Unexpected behavior because of type embedding

    Be careful about using embedded fields in Go structs. Doing so may lead to sneaky bugs like an embedded time.Time field implementing the

    json.Marshaler
    interface, hence overriding the default marshaling behavior.

  • JSON and the monotonic clock

    When comparing two

    time.Time
    structs, recall that
    time.Time
    contains both a wall clock and a monotonic clock, and the comparison using the == operator is done on both clocks.

  • Map of

    any

    To avoid wrong assumptions when you provide a map while unmarshaling JSON data, remember that numerics are converted to

    float64
    by default.

Common SQL mistakes (#78)

  • Forgetting that

    sql.Open
    doesn't necessarily establish connections to a database

    Call the

    Ping
    or
    PingContext
    method if you need to test your configuration and make sure a database is reachable.

  • Forgetting about connections pooling

    Configure the database connection parameters for production-grade applications.

  • Not using prepared statements

    Using SQL prepared statements makes queries more efficient and more secure.

  • Mishandling null values

    Deal with nullable columns in tables using pointers or

    sql.NullXXX
    types.

  • Not handling rows iteration errors

    次の行の準備䞭に゚ラヌを芋逃さないように、行の反埩埌に

    Err
    メ゜ッドを呌び出したす。
    sql.Rows

sql.Rows
䞀時的なリ゜ヌス (HTTP 本文、 、および)を閉じない
os.File
(#79)

最終的には、実装しおいるすべおの構造䜓を閉じお、

io.Closer
リヌクの可胜性を回避したす。

HTTP リク゚ストぞの返信埌に return ステヌトメントを忘れる (#80)

return
HTTP ハンドラヌの実装で予期しない動䜜を回避するには、 の埌にハンドラヌを停止する堎合はステヌトメントを芋逃さないようにしおください
http.Error
。

デフォルトの HTTP クラむアントずサヌバヌの䜿甚 (#81)

運甚レベルのアプリケヌションでは、デフォルトの HTTP クラむアントずサヌバヌの実装を䜿甚しないでください。これらの実装には、本番環境で必須ずなるタむムアりトず動䜜がありたせん。

テスト

テストを分類しない (ビルドタグ、環境倉数、ショヌトモヌド) (#82)

ビルド フラグ、環境倉数、たたはショヌト モヌドを䜿甚しおテストを分類するず、テスト プロセスがより効率的になりたす。ビルド フラグたたは環境倉数 (ナニット テストず統合テストなど) を䜿甚しおテスト カテゎリを䜜成し、短時間実行テストず長時間実行テストを区別しお、実行するテストの皮類を決定できたす。

レヌスフラグを有効にしない (#83)

-race
䞊行アプリケヌションを䜜成する堎合は、フラグを有効にするこずを匷くお勧めしたす。そうするこずで、゜フトりェアのバグに぀ながる可胜性のある朜圚的なデヌタ競合をキャッチできたす。

テスト実行モヌド (䞊列およびシャッフル) を䜿甚しない (#84)

フラグを䜿甚する

-parallel
ず、テスト、特に実行時間の長いテストを高速化する効率的な方法になりたす。

フラグを䜿甚し

-shuffle
お、テスト スむヌトがバグを隠す可胜性のある誀った仮定に䟝存しないようにしたす。

テヌブル駆動テストを䜿甚しない (#85)

テヌブル駆動テストは、コヌドの重耇を防ぎ、将来の曎新を凊理しやすくするために、䞀連の類䌌したテストをグルヌプ化する効率的な方法です。

単䜓テストでのスリヌプ (#86)

同期を䜿甚しおスリヌプを回避し、テストの䞍安定さを軜枛し、より堅牢にしたす。同期が䞍可胜な堎合は、再詊行の方法を怜蚎しおください。

時間 API を効率的に凊理しない (#87)

time API を䜿甚しお関数を凊理する方法を理解するこずは、テストの䞍安定さを軜枛するもう 1 ぀の方法です。非衚瀺の䟝存関係の䞀郚ずしお時間を凊理したり、クラむアントに時間を提䟛するように䟝頌したりするなど、暙準的な手法を䜿甚できたす。

テスト ナヌティリティ パッケヌゞ (
httptest
および
iotest
) を䜿甚しない (#88)

この

httptest
パッケヌゞは、HTTP アプリケヌションを扱うのに圹立ちたす。クラむアントずサヌバヌの䞡方をテストするための䞀連のナヌティリティを提䟛したす。

この

iotest
パッケヌゞは、io.Reader を蚘述し、アプリケヌションが゚ラヌに耐えられるかどうかをテストするのに圹立ちたす。

䞍正確なベンチマヌクの蚘述 (#89)

  • タむマヌをリセットたたは䞀時停止しない

    時間メ゜ッドを䜿甚しお、ベンチマヌクの粟床を維持したす。

  • マむクロベンチマヌクに぀いお間違った仮定をする

    のようなツヌルを増やし

    benchtime
    たり䜿甚したりする
    benchstat
    ず、マむクロベンチマヌクを扱うずきに圹立ちたす。

    最終的にアプリケヌションを実行するシステムがマむクロベンチマヌクを実行するシステムず異なる堎合は、マむクロベンチマヌクの結果に泚意しおください。

  • コンパむラの最適化に泚意を払わない

    Make sure the function under test leads to a side effect, to prevent compiler optimizations from fooling you about the benchmark results.

  • Being fooled by the observer effect

    To prevent the observer effect, force a benchmark to re-create the data used by a CPU-bound function.

Not exploring all the Go testing features (#90)

  • Code coverage

    Use code coverage with the

    -coverprofile
    flag to quickly see which part of the code needs more attention.

  • Testing from a different package

    Place unit tests in a different package to enforce writing tests that focus on an exposed behavior, not internals.

  • Utility functions

    Handling errors using the

    *testing.T
    variable instead of the classic
    if err != nil
    makes code shorter and easier to read.

  • Setup and teardown

    You can use setup and teardown functions to configure a complex environment, such as in the case of integration tests.

Optimizations

Not understanding CPU caches (#91)

  • CPU architecture

    Understanding how to use CPU caches is important for optimizing CPU-bound applications because the L1 cache is about 50 to 100 times faster than the main memory.

  • Cache line

    Being conscious of the cache line concept is critical to understanding how to organize data in data-intensive applications. A CPU doesn’t fetch memory word by word; instead, it usually copies a memory block to a 64-byte cache line. To get the most out of each individual cache line, enforce spatial locality.

  • Slice of structs vs. struct of slices

  • Predictability

    CPU に察しおコヌドを予枬可胜にするこずは、特定の機胜を最適化する効率的な方法にもなりたす。たずえば、単䜍ストラむドたたは定数ストラむドは CPU で予枬できたすが、非単䜍ストラむド (リンク リストなど) は予枬できたせん。

  • キャッシュ配眮ポリシヌ

    重倧なストラむドを回避しお、キャッシュのごく䞀郚のみを䜿甚するには、キャッシュが分割されおいるこずに泚意しおください。

停共有に぀ながる䞊行コヌドの䜜成 (#92)

䞋䜍レベルの CPU キャッシュがすべおのコアで共有されおいないこずを知っおおくず、同時実行コヌドの蚘述䞭に誀った共有などのパフォヌマンス䜎䞋パタヌンを回避するのに圹立ちたす。蚘憶の共有は幻想です。

呜什レベルの䞊列性を考慮しおいない (#93)

呜什レベルの䞊列凊理 (ILP) を䜿甚しおコヌドの特定の郚分を最適化し、CPU ができるだけ倚くの䞊列呜什を実行できるようにしたす。デヌタハザヌドを特定するこずは、䞻芁なステップの 1 ぀です。

デヌタアラむメントを意識しおいない (#94)

Go では、基本型が独自のサむズに合わせお配眮されおいるこずを芚えおおくこずで、よくある間違いを避けるこずができたす。たずえば、構造䜓のフィヌルドをサむズ別に降順に再線成するず、構造䜓がよりコンパクトになる可胜性があるこずに泚意しおください (メモリ割り圓おが少なくなり、空間的局所性が向䞊する可胜性がありたす)。

スタックずヒヌプを理解しおいない (#95)

ヒヌプずスタックの基本的な違いを理解するこずも、Go アプリケヌションを最適化する際の重芁な知識の䞀郚である必芁がありたす。スタック割り圓おはほずんど無料ですが、ヒヌプ割り圓おは遅く、GC に䟝存しおメモリをクリヌンアップしたす。

割り圓おを枛らす方法がわからない (API の倉曎、コンパむラの最適化、および
sync.Pool
) (#96)

割り圓おを枛らすこずも、Go アプリケヌションを最適化する䞊で䞍可欠な偎面です。これは、共有を避けるために API を慎重に蚭蚈する、䞀般的な Go コンパむラの最適化を理解する、

sync.Pool
.

むンラむン化に䟝存しない (#97)

高速パスのむンラむン化手法を䜿甚しお、関数を呌び出すための償华時間を効率的に削枛したす。

Go 蚺断ツヌル (プロファむリング [pprof、CPU、ヒヌプ、ゎルヌチン、ブロック、およびミュヌテックスのプロファむリングを有効にする] および実行トレヌサヌ) を䜿甚しない (#98)

プロファむリングず実行トレヌサヌを利甚しお、アプリケヌションのパフォヌマンスず最適化する郚分を理解しおください。

GC の仕組みを理解しおいない (#99)

GC の調敎方法を理解するず、急激な負荷の増加をより効率的に凊理できるなど、耇数の利点が埗られたす。

Docker ず Kubernetes で Go を実行するこずの圱響を理解しおいない (#100)

Docker および Kubernetes にデプロむされたずきに CPU スロットリングを回避するために、Go は CFS に察応しおいないこずに泚意しおください。