実用 Go言語 ―システム開発の現場で知っておきたいアドバイス

Book description

業務プログラミングの現場でも採用されるようになってきたGo言語。文法はシンプルで学びやすいという特徴を持っていますが、複雑な要件を実現するには、プログラミング言語が提供する構成要素(文法やライブラリ)をさまざまに組み合わせる必要があります。 本書は、そんなGoを使う上でのポイントを単なる文法詳解ではなく「よりGoらしく書くには」「実用的なアプリケーションを書くには」といった観点から紹介します。 構造体やインタフェースの使い方からJSON、CSVファイル、Excel、固定長ファイルの扱い方、またログやテスト、環境構築など現場に即した幅広いトピックについて、「Goらしいプログラムの書き方」をその背景と共に教えてくれる先輩のような書籍です。

Table of contents

  1. 大扉
  2. 著作権表記
  3. まえがき
    1. なぜGoなのか?上司を説得する方法
      1. Goは学びやすい
      2. 実装の効率が高いのにパフォーマンスが高い
      3. Goはクラウドネイティブ言語
      4. 上司の説得方法のまとめ
    2. 意見と質問
    3. 表記上のルール
    4. サンプルコードの使用について
  4. 「Goらしさ」に触れる
    1. 変数やパッケージ、メソッドなどに名前を付けるには
      1. 変数名
      2. パッケージ名
      3. インタフェース名
      4. レシーバー名
    2. 定数の使い方
      1. 型のない定数を定義する
      2. 型付きconst変数を定義する
      3. 他言語との違い
      4. 定数でerror型のインスタンスを提供する
    3. iotaを用いて列挙型を実現する
      1. それぞれ、ユニークな値を持つ定数を定義
      2. iotaの挙動
      3. 組み合わせてフラグとして利用する定数の実現
      4. iotaを使うべきでない時
      5. 文字列として出力可能にする
    4. Goのエラーを扱う
      1. Goのエラーは値
      2. panic()は使わない
      3. Goのエラーハンドリング
      4. 他の言語との違い
    5. 変数は短縮形式:=とvarのどちらを使うべきか
    6. 関数のオプション引数
      1. 別名の関数によるオプション引数
      2. 構造体を利用したオプション引数
      3. ビルダーを利用したオプション引数
      4. Functional Optionパターンを使ったオプション引数
      5. どの実装方法を選択すべきか
    7. プログラムを制御する引数
      1. コマンドライン引数
      2. 環境変数
    8. メモリ起因のパフォーマンス低下を解消する
      1. スライスのメモリ確保を高速化する
      2. マップのメモリ確保を高速化する
      3. deferの落とし穴
    9. 文字列の結合方法
    10. 日時の取り扱い
      1. 日時のtime.Timeの取得
      2. 時間を表すtime.Duration
      3. ウェブフロントエンドとのデータの交換
      4. 翌月を計算するときのはまりどころ
    11. まとめ
  5. 定義型
    1. 型を定義してデータの不整合を防止する
      1. Goにおける型の定義
    2. 既存のデータ型を拡張する
      1. メソッドを追加して組み込み型を拡張する
      2. 拡張した組み込み型で、元となる基底型の挙動を利用する
      3. ファクトリー関数を用意して定義した型を使いやすくする
    3. 定義型を作成してアプリケーションドメインに対応する
      1. スライスへの型定義
      2. 値への型定義
      3. 列挙への型定義
      4. 構造体への型定義
    4. 型の変換
      1. 型変換(type conversion)によって型をキャストする
    5. 機密情報を扱うフィールドを定義して出力書式をカスタマイズする
      1. 実装方法
  6. 構造体
    1. 構造体の基本的な使い方
    2. 構造体をインスタンス化する3つの方法
      1. ファクトリー関数
    3. 構造体にメソッドを定義する
      1. 値レシーバーとポインターレシーバーのどちらを使えば良いか
      2. レシーバーはnilでもメソッドは呼べる
      3. インスタンスからメソッドを取り出して関数型として使う
      4. クロージャを使ってメソッドを再現する
      5. ジェネリクスとメソッド
    4. 構造体の埋め込みで共通部分を使いまわす
    5. タグを使って構造体にメタデータを埋め込む
      1. タグの記法
      2. タグを使った構造体へのデータの書き込み
      3. タグを使った構造体からのデータの読み込み
      4. タグのまとめ
    6. 構造体を設計するポイント
      1. ポインター型として扱う必要があるケース
      2. 値として扱える場合
      3. ミュータブルな構造体とイミュータブルな構造体
      4. ゼロ値の動作を保証するかどうか
      5. 実装方法を選択するポイント
    7. 空の構造体を使ってゴルーチン間での通知を行う
    8. 構造体のメモリ割り当てを高速化する
    9. 構造体とオブジェクト指向の違いを知る
      1. 構造体の用途
      2. 構造体の埋め込みは継承ではない
      3. テンプレートメソッドパターンではなく、ストラテジーパターン
      4. あえてオーバーライドを実装する
  7. インタフェース
    1. 柔軟なコードを書くインタフェースの利用法
      1. まとめ
    2. あらゆる型のデータを格納するany
    3. インタフェースのキャスト
      1. 型アサーション・型スイッチの基本の書き方
      2. 他のメソッドを持っているかの問い合わせ
      3. スライスのキャスト
    4. インタフェースの合成
    5. 実装を切り替えるためのさまざまな方法
      1. 基本の分岐
      2. 中間の方法
      3. インタフェース利用と設計のポイント
      4. まとめ
  8. エラーハンドリング
    1. エラーの書き方
      1. errors.New
      2. fmt.Errorf
      3. 独自のエラー型
      4. エラーのラップ、アンラップ
      5. エラーの色々な比較
      6. スタックトレースをどう出すのか
    2. エラーハンドリングの基本テクニック
      1. 呼び出し元に関数の引数などの情報を付与してエラーを返す
      2. ログを出力して処理を継続する
      3. リトライを実施する
      4. リソースをクローズする
      5. 複数のエラーをまとめる方法
    3. エラーのチェック忘れを予防する
      1. kisielk/errcheckの利用
      2. %w利用箇所の制限
  9. パッケージ、モジュール
    1. プロジェクト構成の事前知識
      1. パッケージ
      2. パッケージのimportが循環してはいけない
      3. 親パッケージと子パッケージは独立したパッケージ
      4. モジュール
      5. セマンティックバージョニング
      6. 相対パスでのimportはできない
      7. internal
      8. 無視されるフォルダ
      9. go gettable
      10. GOPATH
    2. Go Modulesで開発環境のパッケージを管理する
      1. Go Modulesの概要
    3. Goプロジェクトのライフサイクル
    4. Goプロジェクトのモジュール内のパッケージ構成
      1. 最低限のパッケージ構成
      2. パッケージを階層化する
      3. ドメイン/レイヤー vs レイヤー/ドメイン
      4. 開発時に使うツールの追加
      5. まとめ
    5. Go Modulesの実践的な使い方
      1. 1リポジトリ、マルチモジュール構成
      2. プライベートリポジトリのモジュールを参照する方法
      3. フォークしたモジュールを参照する方法
      4. モジュールのキャッシュ
      5. 依存するモジュールの可用性の考慮
    6. 静的なプラグイン機構を実現する
      1. プラグイン機能の要件
      2. 静的リンクを使ったプラグイン機構
    7. 初期化の順序を制御する
      1. パッケージの読み込み順
      2. パッケージ内部の初期化の順序
  10. Goプログラミングの環境を整備する
    1. エディタとIDE
      1. Visual Studio Code
      2. VS Codeの便利な機能
      3. GoLand
    2. ランタイムのサポート
      1. Go言語自体のサポート
    3. Linterを使ってコードを静的解析する
      1. go vet
      2. golangci-lint
      3. エディタに組み込む
    4. よく使われるビルドフラグ
      1. バイナリサイズを小さくする
      2. ビルド時のパスを削除する
      3. 環境変数CGO_ENABLEDでCGOを制御する
      4. ビルドのバイナリにバージョン番号を埋め込む
      5. ビルド時に対象のOS/アーキテクチャを指定する
    5. CI(継続的インテグレーション)を導入する
      1. GitHub Actions
      2. CircleCI
    6. EditorConfigを導入する
      1. EditorConfigの導入方法
    7. Makefileを導入する
      1. Makefileの書き方
    8. .gitignoreの準備
    9. プロキシのある環境における開発環境の整備
      1. プロキシサーバーの設定
      2. Gitにおける設定
      3. 環境変数での設定
  11. さまざまなデータフォーマット
    1. JSONファイルを扱う
      1. 基本的なエンコードとデコード
    2. CSVファイルを扱う
      1. CSV形式のファイルを読み込む
      2. CSV形式でファイルに書き込む
      3. BOM付きファイルの扱い
      4. Shift-JIS(Windows-31J)を扱うには
      5. コメントアウトされた行をスキップしたい
      6. CSV行を構造体で表現する
      7. encoding/csvの設定をgocarina/gocsvに引き継ぐ
      8. CSVのエンコード/デコードを拡張する
      9. 巨大なCSVファイルを扱いたい場合(逐次処理で書き込みたい場合)
      10. マルチレイアウトCSVを処理したい
    3. Microsoft Excelファイルを扱う
      1. Excelファイルに対する書き込み・読み込み
      2. 複数レコードを書き込む方法
      3. Excelファイルを読み取る
      4. 構造体へのマッピング付きで読み取る
    4. 固定長データを扱う
      1. 固定長データファイルとは
      2. 標準ライブラリで固定長データを扱う
      3. 固定長の各カラムを構造体のメンバーで表現したい
      4. 固定長データに関するさまざまな考慮事項
  12. Goとリレーショナルデータベース
    1. データベースの基本的な利用法
      1. データベースに接続する
      2. クエリーを発行する
    2. トランザクションを扱うには
      1. シンプルに実装する方法
      2. deferを使ってロールバックを行う方法
      3. トランザクションラッパーでトランザクション制御を実装と分離する方法
    3. コネクションプールのパラメーターをチューニングする
    4. クエリーをキャンセルする
      1. コンテキスト付きのdatabase/sql関数を使用する
    5. アプリケーションでクエリーをロギングする
      1. ドライバーを使ってクエリーをロギング
      2. ラッパーのドライバーを使用してクエリーをロギング
    6. 大量のデータをバッチインサート
      1. プリペアードステートメントを使う
      2. バッチインサートを使う
      3. データベース組み込みの関数を使う
      4. まとめ
    7. 共通カラムをうまく扱うには
      1. 共通カラムでよく利用される項目
      2. 共通カラムのアプリケーションからの扱い方
      3. 共通カラムを構造体の埋め込みで扱う
      4. 設計の方針
    8. データベースアクセスをともなう実装のテスト
      1. 本物のデータベースを使ったテスト
      2. モックを使ったテスト
    9. サードパーティーのライブラリを使ったあれこれ
      1. サードパーティーライブラリの分類
      2. スキーマドリブンでアプリケーションを開発
      3. クエリードリブンでアプリケーションを開発
      4. クエリーのロギング
  13. HTTPサーバー
    1. 現代のウェブアプリケーションサーバーの役割
    2. ウェブプログラミングの基本
      1. HTTPサーバーを実装する
      2. JSONデータの読み書き
      3. リクエストのバリデーション
      4. 必須チェックのハマりどころ
    3. HTTPのリクエストのパース
      1. クエリーのパース
      2. ファイルのアップロードの処理
    4. ルーター
      1. 標準ライブラリのhttp.ServeMux
      2. サードパーティー製のルーター
      3. まとめ
    5. Middlewareパターンを使って処理を分離する
      1. Middlewareの仕組み
      2. ステータスコードのキャプチャ
      3. ハンドラー内部でのpanicの防御
      4. DBのトランザクション制御
      5. タイムアウト設定
      6. レートリミット(速度制限)
      7. まとめ
    6. シングルページアプリケーションの静的ファイルを配信する
      1. フロントエンドの開発
      2. バックエンドの作成
    7. APIドキュメントを生成する
  14. HTTPクライアント
    1. net/httpを使ったHTTPクライアントの基本
      1. http.Get
      2. http.Post
      3. http.Clientを作成してリクエスト
    2. RoundTripperインタフェースによって処理を分離する
      1. RoundTripperでロギングする
      2. RoundTripperで認証認可
      3. RoundTripperでリトライ
    3. リトライ時に考慮するべき点
      1. すべてをリトライしない
      2. Exponential backoff
      3. Retry-Afterヘッダーによる待機時間
      4. リトライするための待機処理にtime.Sleepを使わない
    4. プロキシサーバーを突破する
      1. net/httpのプロキシサーバー設定
      2. SSL証明書エラーがでる場合のプロキシサーバー対応
  15. ログとオブザーバビリティ
    1. ログをめぐる、出力の仕組みの変化
    2. ログに出力すべき内容を決めるには
      1. どんな目的でログを利用するか
      2. ログ出力の項目
      3. 出力頻度
      4. ログとセキュリティ事故
      5. クラウド時代のログサービス
    3. 標準ライブラリでログを出力する
      1. ユニットテストの中のログ出力
      2. ログ出力のカスタマイズ
    4. 構造化ログを出力する
      1. zerologの基本とログレベル
      2. zerologの基本: さまざまな情報
      3. ログにエラーコードを埋め込む
      4. ウェブサービスのミドルウェアでログを出力する
    5. エラーとログ出力
      1. log.Fatal()とpanic()の違い
      2. これらの関数で強制終了をしても良い場所
    6. net/httpのエラーログをカスタマイズする
    7. 分散システムの動作を確認するには
      1. Instrumentation/Exporter
      2. 分散トレース
  16. テスト
    1. Goのテストの書き方の基礎
    2. Table Driven Testを実装する
      1. Table Driven Test とは
      2. Table(テストケース)
      3. テストの実行
    3. テストに事前事後の処理を追加する
    4. ヘルパー関数
      1. ヘルパー関数を_test.goというテストコードの中に書く
      2. テストヘルパー用のパッケージを作成する
    5. ウェブサーバーのハンドラーをテストする
      1. サーバー全体のテスト
      2. ハンドラー単体のテスト
    6. テストの落とし穴の回避
      1. テストの分割
      2. テストの順序依存の排除
      3. キャッシュの削除
      4. 時間がかかるようになったテストへの対処
    7. testifyを使う
    8. 構造体の比較にgo-cmpを使う
      1. go-cmpを使う理由
      2. go-cmpのTips
      3. まとめ
    9. テストが書きにくいものをテストする
      1. シンプルな入出力のテスト
      2. 変換が必要な入出力のテスト
      3. さらに複雑な入出力のテスト
      4. 時刻をともなうテスト
      5. まとめ
    10. 品質を保証するテストを実装する
      1. ペアワイズ法を使ったテストパターンの考慮もれ防止
      2. カバレッジ
      3. プロパティベーステスト
      4. まとめ
    11. go testでベンチマークを取る
    12. ドキュメントに出力するExampleをコードに記述する
  17. クラウドとGo
    1. コンテナの起動
      1. コンテナとDocker
      2. 開発での使い方
      3. docker-compose.yamlのサンプル
      4. docker image pullとプロキシ
      5. まとめ
    2. コンテナ用イメージの作成
      1. Dockerを使ったイメージのビルド
      2. Cloud Native Buildpacksとkoによるイメージの作成
      3. まとめ
    3. クラウドサービスにデプロイする
      1. Amazon ECSへのデプロイ
      2. AWS LambdaでWebサーバーを動かす
      3. Cloud RunでWebサーバーを動かす
  18. クラウドのストレージ
    1. AWS S3
      1. AWS SDK for Go v2
      2. Go CDK
    2. Amazon DynamoDB
      1. APIを使ってDynamoDBにアクセスする
  19. エンタープライズなGoアプリケーションと並行処理
    1. 並行処理の基本を知る
      1. ゴルーチン
      2. チャネル
      3. Goの並行処理の内部実装
    2. 同時に動作するスレッドを1つに制限する
      1. ゴルーチンセーフ
    3. ゴルーチンプールを使って複数のタスクを実行
      1. タスクの分量がわからない場合
      2. あらかじめタスクの分量がわかっている場合
      3. 処理速度を制限する
      4. ボトルネックと、バッファつきチャネルの効能
    4. チャネルのブロッキングを中断する(何も起きていないことを検知する)
      1. 受信の方法
    5. ゴルーチン間のイベント伝達
      1. Goにおける例外処理:コンテキスト
      2. context.Contextを使ったエラー通知
    6. 処理の分岐と待ち合わせをしたい(ファンアウト・ファンイン)
      1. sync.WaitGroup
      2. errgroup.Group
    7. 処理の待ち合わせをしたい(Future/Promiseパターン)
    8. ウェブサービスでセッションの情報を共有する
      1. 子側のコンテキストで追加された情報を親コンテキストで読み取る
    9. ゴルーチンリークの見つけ方
      1. ループによるリーク
      2. ループ以外のチャネル待ちによるリーク
      3. テストで検知する
  20. 駆け足で学ぶGoの基礎
    1. Hello World
    2. リテラル・変数宣言
      1. シャドーイング
    3. 名前
    4. コメント
    5. 型と変換
    6. ポインター
    7. ゼロ値
    8. スライス
    9. マップ
    10. 制御構文
      1. if
      2. forループ
      3. switch
    11. 関数
      1. deferで後処理の関数の実行予約
    12. エラー処理
    13. 構造体
    14. ライブラリのインポート
    15. ウェブアプリケーション
    16. まとめ
  21. Goの最新情報を知るための情報源
    1. 信頼できる情報源
    2. Goの学習に使える教材
    3. GoDocの読み方
    4. まとめ
  22. あとがき
    1. おわりに
    2. 著者紹介
    3. カバーの説明
  23. 奥付

Product information

  • Title: 実用 Go言語 ―システム開発の現場で知っておきたいアドバイス
  • Author(s): 渋川 よしき, 辻 大志郎, 真野 隼記
  • Release date: April 2022
  • Publisher(s): O'Reilly Japan, Inc.
  • ISBN: 9784873119694

You might also like

book

入門 監視 ―モダンなモニタリングのためのデザインパターン

by Mike Julian, 松浦 隼人

本書は、システムのどの部分をどのように監視すべきか、また監視をどのように改善していくべきかについて解説する書籍です。前半で監視のベストプラクティス、デザインパターン/アンチパターンを示して、監視の基本原則を詳しく説明し、後半でフロントエンド、アプリケーション、サーバ、ネットワーク、セキュリティの各テーマで強力な監視の基盤を設計して実装するための方法を示します。監視対象が変化し、システムアーキテクチャが進化する中で、従来から変わらない監視の基本を示しながら、時代に合った監視の実践を解説する本書は、監視についての理解を深めたいエンジニア必携の一冊です。

book

リーダーの作法 ―ささいなことをていねいに

by Michael Lopp, 和智 右桂

リーダーシップは一部の人だけに与えられる天職であり、複雑で膨大なリーダーシップの哲学を実践しなければならないと思われがちですが、そんなことはありません。ささいな行動を日々繰り返すことで、お互いを尊敬し、信頼し合うチームを作ることができます。 Netscapeでマネージャー、Appleでディレクター、Slackでエグゼクティブを経験した著者が、それぞれの立場のリーダーに必要な振る舞いを30のエッセイで紹介します。 1on1での傾聴、信頼関係の築き方、仕事の任せ方、メンバーのほめ方、チーム内のうわさ話への対応、組織の文化の作り方など、マネジメントの場面で出会うさまざまなテーマをとりあげ、リーダーとしての具体的な行動や考え方を解説します。

book

マスタリングLinuxシェルスクリプト 第2版 ―Linuxコマンド、bashスクリプト、シェルプログラミング実践入門

by Mokhtar Ebrahim, Andrew Mallett, 萬谷 暢崇, 原 隆文

Linuxシェルスクリプトの解説書。その中でも特にbashのシェルスクリプティングに焦点を当てています。シェルスクリプトの書き方、デバッグ方法、bashプログラミングの基本といったシェルスクリプティングの基礎から、sedやAWKなど各種ツールとの連携といった実践的な応用までを体系的に解説します。WebサーバーなどのLinuxシステムの管理を任されるようになった初級の管理者にも、もっと高度で実践的なテクニックを必要としている中級の管理者や開発者にも広く役に立つ内容です。

book

ハイパフォーマンス ブラウザネットワーキング ―ネットワークアプリケーションのためのパフォーマンス最適化

by Ilya Grigorik, 和田 祐一郎/株式会社プログラミングシステム社

現代のアプリケーションエンジニアは、UIやデータ処理、開発言語、プラットフォームの仕様や癖だけでなく、サーバやネットワークについても、上から下まで、表から裏まで広く知ることを求められます。本書は「ブラウザ」に関連し、インターネットで使用されるさまざまなネットワーク技術をまとめたものです。HTTP/2.0やWebRTCなどの最新技術、WebSocketやXMLHttpRequestなどのブラウザAPI、そしてそれらの土台となるTCPやUDPやトランスポート層についてまでを幅広くカバーします。また改善前後の性能・速さを可能な限り具体化し、それぞれの場面においてのパフォーマンス改善幅を示します。