インプレス[コンピュータ・IT]ムック Go言語 100Tips ありがちなミスを把握し、実装を最適化する
インプレス / 2023年08月18日 / 全415ページ
本書では、Go言語による開発でよく見られる100の間違いを取り上げ、その例を検証し、背景にある事柄を掘り下げます。さらに、間違いを回避するヒント/テクニックを紹介、間違いを回避できるようにします。本書で取り上げるのは、バグ、不必要な複雑さ、可読性の低下、最適ではないソフトウェア構成、APIの利便性の欠如、生産性の欠如などです。Go言語の文法のほか、エラー管理、並行処理、標準ライブラリ、テストなど、さまざまなカテゴリーにおける間違いを見ていきます。Goプログラマーであれば必ず押さえておきたい内容です。
目次
- サンプルコード・正誤表・商標について
- The Land of Go Mistakes
- 献辞
- 推薦の言葉
- 著者紹介
- 目次
- まえがき
- 謝辞
- 本書について
- 第1章 Go言語―学ぶのは容易、習得は難しい1.1 Goの概要
- 1.2 単純であれば容易であるとは限らない1.3 100個のGoの間違い
- 1.3.1 バグ
- 1.3.2 不必要な複雑さ1.3.3 可読性の低下1.3.4 最適ではない、または慣用的ではないソフトウェア構成
- 1.3.5 APIの利便性の欠如1.3.6 最適化されていないコード1.3.7 生産性の欠如
- 第2章 コードとプロジェクト構成2.1 No.1:意図しない変数シャドウイング
- 2.2 No.2:不必要にネストしたコード
- 2.3 No.3:init関数の誤用2.3.1 init関数の概念
- 2.3.2 init関数を使うべき場合
- 2.4 No.4:ゲッターとセッターの多用
- 2.5 No.5:インタフェース汚染2.5.1 インタフェースの概念
- サンプルコード・正誤表・商標について
- The Land of Go Mistakes
- 献辞
- 推薦の言葉
- 著者紹介
- 目次
- まえがき
- 謝辞
- 本書について
- 第1章 Go言語―学ぶのは容易、習得は難しい1.1 Goの概要
- 1.2 単純であれば容易であるとは限らない1.3 100個のGoの間違い
- 1.3.1 バグ
- 1.3.2 不必要な複雑さ1.3.3 可読性の低下1.3.4 最適ではない、または慣用的ではないソフトウェア構成
- 1.3.5 APIの利便性の欠如1.3.6 最適化されていないコード1.3.7 生産性の欠如
- 第2章 コードとプロジェクト構成2.1 No.1:意図しない変数シャドウイング
- 2.2 No.2:不必要にネストしたコード
- 2.3 No.3:init関数の誤用2.3.1 init関数の概念
- 2.3.2 init関数を使うべき場合
- 2.4 No.4:ゲッターとセッターの多用
- 2.5 No.5:インタフェース汚染2.5.1 インタフェースの概念
- 2.5.2 インタフェースを使う場合
- 2.5.3 インタフェース汚染
- 2.6 No.6:生産者側のインタフェース
- 2.7 No.7:インタフェースを返す
- 2.8 No.8:anyは何も伝えない
- 2.9 No.9:ジェネリクスをいつ使うべきかで混乱する2.9.1 ジェネリクスの概念
- 2.9.2 一般的な用途と誤用
- 2.10 No.10:型埋め込みで起こり得る問題点を意識していない
- 2.11 No.11:関数オプションパターンを使わない
- 2.11.1 Config構造体
- 2.11.2 ビルダーパターン
- 2.11.3 関数オプションパターン
- 2.12 No.12:プロジェクトの誤った構成2.12.1 プロジェクトの構造
- 2.12.2 パッケージ構成
- 2.13 No.13:ユーティリティパッケージの作成
- 2.14 No.14:パッケージ名の衝突を無視する
- 2.15 No.15:コードのドキュメントがない
- 2.16 No.16:リンターを使わない
- 第3章 データ型3.1 No.17:8進数リテラルで混乱を招く
- 3.2 No.18:整数のオーバーフローを無視する3.2.1 整数に関する概念
- 3.2.2 1を加算したときに整数のオーバーフローを検出する
- 3.2.3 加算時の整数オーバーフローの検出3.2.4 乗算時の整数オーバーフローの検出
- 3.3 No.19:浮動小数点を理解していない
- 3.4 No.20:スライスの長さと容量を理解していない
- 3.5 No.21:非効率なスライスの初期化
- 3.6 No.22:nilスライスと空スライスに混乱する
- 3.7 No.23:スライスが空か否かを適切に検査しない
- 3.8 No.24:スライスのコピーを正しく行わない
- 3.9 No.25:スライスへのappendによる予期しない副作用
- 3.10 No.26:スライスとメモリリーク3.10.1 容量のリーク
- 3.10.2 スライスとポインタ
- 3.11 No.27:非効率なマップの初期化3.11.1 マップの概念
- 3.11.2 初期化
- 3.12 No.28:マップとメモリリーク
- 3.13 No.29:値の比較の誤り
- 第4章 制御構造4.1 No.30:rangeループで要素がコピーされることを無視する4.1.1 rangeループの概念
- 4.1.2 値のコピー
- 4.2 No.31:rangeループでの引数の評価方法を無視する
- 4.2.1 チャネル
- 4.2.2 配列
- 4.3 No.32:rangeループでポインタ要素を使う影響を無視する
- 4.4 No.33:マップの反復処理で誤った仮定をする4.4.1 反復処理での順序
- 4.4.2 反復処理中のマップへの挿入
- 4.5 No.34:break文の仕組みを無視する
- 4.6 No.35:ループ内でdeferを使う
- 第5章 文字列5.1 No.36:ルーンの概念を理解していない
- 5.2 No.37:不正確な文字列の反復
- 5.3 No.38:Trim関数の誤用
- 5.4 No.39:最適化されていない文字列の連結
- 5.5 No.40:無駄な文字列変換
- 5.6 No.41:部分文字列とメモリリーク
- 第6章 関数とメソッド6.1 No.42:どちらのレシーバ型を使うべきかわかっていない
- 6.2 No.43:名前付き結果パラメータを使わない
- 6.3 No.44:名前付き結果パラメータによる意図しない副作用
- 6.4 No.45:nilレシーバを返す
- 6.5 No.46:ファイル名を関数の入力として使う
- 6.6 No.47:deferの引数やレシーバの評価方法を無視している6.6.1 引数の評価
- 6.6.2 ポインタレシーバと値レシーバ
- 第7章 エラー管理7.1 No.48:パニックを発生させる
- 7.2 No.49:エラーをラップすべきときを無視する
- 7.3 No.50:エラー型を不正確に検査する
- 7.4 No.51:エラー値を不正確に検査する
- 7.5 No.52:エラーを2度処理する
- 7.6 No.53:エラーを処理しない
- 7.7 No.54:deferでエラーを処理しない
- 第8章 並行処理:基本編8.1 No.55:並行処理と並列処理を混同する
- 8.2 No.56:並行処理は常に高速であると考える8.2.1 Goのスケジューリング
- 8.2.2 並列マージソート
- 8.3 No.57:チャネルとミューテックスの使い分けに悩む
- 8.4 No.58:競合問題を理解していない8.4.1 データ競合と競合状態
- 8.4.2 Goメモリモデル
- 8.5 No.59:作業負荷の種類による並行処理の影響を理解していない
- 8.6 No.60:Goのコンテキストを誤解する8.6.1 デッドライン
- 8.6.2 キャンセルシグナル
- 8.6.3 コンテキスト値
- 8.6.4 コンテキストのキャンセルを捕捉する
- 第9章 並行処理:実践編9.1 No.61:不適切なコンテキストの伝搬
- 9.2 No.62:ゴルーチンを停止するタイミングをわからずに起動する
- 9.3 No.63:ゴルーチンとループ変数の扱いに注意しない
- 9.4 No.64:selectとチャネルを使って、決定的な動作を期待する
- 9.5 No.65:通知チャネルを使わない
- 9.6 No.66:nilチャネルを使っていない
- 9.7 No.67:チャネルの大きさに迷う
- 9.8 No.68:文字列のフォーマットで起こり得る副作用を忘れる9.8.1 etcdのデータ競合
- 9.8.2 デッドロック
- 9.9 No.69:appendでデータ競合を生み出す
- 9.10 No.70:スライスとマップで誤ったミューテックスを使う
- 9.11 No.71:sync.WaitGroupの誤用
- 9.12 No.72:sync.Condの存在を忘れている
- 9.13 No.73:errgroupを使わない
- 9.14 No.74:syncパッケージの型をコピーする
- 第10章 標準ライブラリ10.1 No.75:誤った時間の長さを提供する
- 10.2 No.76:time.Afterとメモリリーク
- 10.3 No.77:よくあるJSON処理の間違い10.3.1 型埋め込みによる予期しない動作
- 10.3.2 JSONとモノトニッククロック
- 10.3.3 anyのマップ
- 10.4 No.78:よくあるSQLの間違い10.4.1 sql.Openは必ずしもデータベースへのコネクションを確立しないことを忘れる
- 10.4.2 コネクションプールについて忘れている
- 10.4.3 プリペアドステートメントを使わない
- 10.4.4 null値の誤った扱い
- 10.4.5 行の反復処理時のエラーに対処しない
- 10.5 No.79:一時的な資源をクローズしない10.5.1 HTTPボディ
- 10.5.2 sql.Row
- 10.5.3 os.Fil
- 10.6 No.80:HTTPリクエストに応答した後にreturn文を忘れる
- 10.7 No.81:デフォルトのHTTPクライアントとサーバーを使う10.7.1 HTTPクライアント
- 10.7.2 HTTPサーバー
- 第11章 テスト11.1 No.82:テストを分類しない
- 11.1.1 ビルドタグ
- 11.1.2 環境変数
- 11.1.3 ショートモード
- 11.2 No.83:-raceフラグを有効にしない
- 11.3 No.84:テスト実行モードを使わない11.3.1 -parallelフラグ
- 11.3.2 -shuffleフラグ
- 11.4 No.85:テーブル駆動テストを使わない
- 11.5 No.86:単体テストでスリープする
- 11.6 No.87:time APIを効率よく扱わない
- 11.7 No.88:テスト用ユーティリティパッケージを使っていない11.7.1 httptestパッケージ
- 11.7.2 iotestパッケージ
- 11.8 No.89:不正確なベンチマークを書く
- 11.8.1 タイマーをリセットしたり一時停止したりしない
- 11.8.2 マイクロベンチマークについて間違った仮定をする
- 11.8.3 コンパイラの最適化に注意を払わない
- 11.8.4 観察者効果にだまされる
- 11.9 No.90:Goテストの機能をすべて使いこなしていない11.9.1 コードカバレッジ
- 11.9.2 別パッケージからのテスト
- 11.9.3 ユーティリティ関数
- 11.9.4 事前準備と事後処理
- 第12章 最適化12.1 No.91:CPUキャッシュを理解していない
- 12.1.1 CPUアーキテクチャ
- 12.1.2 キャッシュライン
- 12.1.3 構造体のスライスとスライスの構造体
- 12.1.4 予測可能性
- 12.1.5 キャッシュ配置ポリシー
- 12.2 No.92:偽共有につながる並行コードを書く
- 12.3 No.93:命令レベルの並列処理を考慮しない
- 12.4 No.94:データアラインメントを意識していない
- 12.5 No.95:スタックとヒープを理解していない12.5.1 スタックとヒープ
- 12.5.2 エスケープ分析
- 12.6 No.96:割り当てを減らす方法を知らない
- 12.6.1 APIの変更12.6.2 コンパイラの最適化
- 12.6.3 sync.Pool
- 12.7 No.97:インライン展開に頼らない
- 12.8 No.98:Goの診断ツールを使っていない12.8.1 プロファイリング
- 12.8.2 実行トレーサー
- 12.9 No.99:GCの仕組みを理解していない12.9.1 ガベージコレクタの概念
- 12.9.2 GCの例
- 12.10 No.100:DockerやKubernetesでGoを実行することによる影響を理解していない
- 訳者あとがき
- 索引
- 訳者紹介・レビュアー・STAFF LIST
- 奥付
※このデジタル雑誌には目次に記載されているコンテンツが含まれています。それ以外のコンテンツは、本誌のコンテンツであっても含まれていません のでご注意ください。
※電子版では、紙の雑誌と内容が一部異なる場合や、掲載されないページがある場合があります。