Goなんもわからん

環境
- go
- goa v1
などなど

テスト
コマンドなど
go test ./...
PJ全部のテストコードを実行
go test ./hoge
hoge直下のテストコードを実行
go test ./hoge -run TestFuga
特定のテストだけ実行
詳細なログを出す場合は -v
オプションをつける
カバー率を知りたい場合は -cover
オプションをつける(カバレッジ)
gomock
↑のは2023年にサポート終了している
後継は https://github.com/uber-go/mock になる

クリーンアーキテクチャ
って何
- ビジネスロジック(ドメイン)を中心に置き、インターフェースの層や技術を外側に配置する設計
- システムの保守性・拡張性・テスト容易性を高めるためのアーキテクチャ
- 役割が明確に分離する
- 1つ変更しても、他の層には影響がないように作ることができる
- 既存機能の改修の場合、手を入れる場所が明確になる
- 他の機能への影響を減らせる
- テストコードを書きやすい
- バグがあった時にどこが原因かの特定がしやすい
例:じゃんけんアプリを作るとする
グーはチョキに勝つ、というのがメインのルール(ビジネスロジック)
→これが、MySQL使おうが、Oracleだろうが、この根底のロジックは変わらないよね
→つまり、何かロジック以外の部分を変えたくなってもロジックには影響しないように作ろう!ということ
ビジネスロジック
システム固有の処理を行う部分・・・みたいなイメージ
MVC との違い
- 役割、層の違い
- MVC:3つに分かれる
- クリーン(略):4つの層に分かれるのがベース。なんならもっと細かい場合もある
- 依存の違い
- MVC:依存の方向性は決められていない、VCは依存しているし、CMは依存していたりする
- クリーン:依存性の方向性に厳格なルールがある、常に内側から外側にのみ発生する、逆はありえない
- ビジネスロジック(達成したいルール、処理)
- MVC:通常はMに含まれるが実装による
- クリーン:2つの層に分ける
- エンティティ層:最重要のビジネスルール
- ユースケース層:アプリ固有のルール
構成例
- model
- MVCで言えばMの部分
- データ構造とビジネスルールを定義(ドメインエンティティ)
- じゃんけんで言えば
- データ構造:「手の種類」「勝敗結果」「ゲーム履歴」など
- ビジネスルール:どの手がどの手に勝つのかの判定
- usecase
- 機能のインターフェース
- じゃんけんで言えば
- じゃんけんを始める、履歴を取得する などの機能のIF部分
- interactor
- 実際のusecaseの実装部分
- じゃんけんで言えば
- 実際に対戦を始める時の処理、履歴を取得する処理
- repository
- データの操作に関するインターフェース
- じゃんけんで言えば
- ゲーム履歴を保存、取得 などのDBに関わるIF部分
- datastore
- 実際のrepositoryの実装部分
- じゃんけんで言えば
- 履歴テーブルへの保存、取得の処理
処理の流れ
どういう処理の流れになるのか?
じゃんけんしたいよ!
- フロントから「POST /janken」が来る
- リクエスト受け取り、usecaseを呼ぶ
- usecase を実装しているinteractorが実行。処理に必要な情報が欲しいのでrepositoryを呼ぶ
- repositoryを実装しているdatastoreが実行。実際のDB処理を行って情報を取得
- datastoreから情報を受け取って必要な処理を行う、usecaseの出力DTOに情報をつめる
- interactorから情報を受け取ってフロントに返す

DTO
Data Transfer Object(データ転送オブジェクト)のこと
システムの層と層の間(webapi と usecase の間)でデータを受け渡すためのハコ
例:じゃんけん履歴を日付で絞り込んで取得したい
リクエストDTO
(api はHTTPリクエストを受け取ってこのHistoryInに情報をつめる)
type HistoryIn struct {
PlayerID string // 誰の履歴か
FromDate string // いつから(例: "2025-08-01")
ToDate string // いつまで(例: "2025-08-20")
Page int // ページ番号(ページング)
PageSize int // 1ページあたり件数
}
レスポンスDTO
(Interactor はこれを使ってRepository に問い合わせ、結果をHistoryListOutにつめて apiに返す)
type HistoryListOut struct {
Matches []HistoryOut // 履歴の配列
Total int // 全件数(ページング用)
}

Goa
- REST API を使いたい時に利用することが多い
- ビジネスロジック中心で開発ができる
- Swaggerなど自動生成される
- Disignのファイルを作った後、
goagen
のコマンドを実行すると、色々と必要なファイルや関数を自動生成してくれる
- Disignのファイルを作った後、
今はv3が一番新しいのかな?(なお使っているのはv1)

DI
依存性の注入
→処理に必要なオブジェクトを外部から注入できるようにする ということ
関数とかにベタ書きしないで、別のIFで管理しようねーみたいな感じ
→関数とかにベタ書きしちゃうと柔軟性がなくなったりテストしにくかったり・・・ということが発生する
たとえばDBにアクセスする関数内でMySQLにアクセスするよ!とかやってる場合
→DBをOracleとかに変えたらどうするの?関数内も変える必要あるよね?
という問題が発生する
↓
外から注入する(関数外でDBを指定する)ことで、DBが変わったらそのIF部分のみ変えればよいよね〜
(つまりクリーンアーキテクチャするにはDIの考えが必須という感じなのかな?)
DIコンテナ
DIを簡単に使えるようにするツール
たとえばwire というライブラリを使う
wire
(2025年8月にサポート終了してるやんけ)
- wire.goを書く
- wire.go から wire_gen.go が生成される(
wire gen
を実行する) - main.go みたいな全体管理のファイルから wire_gen.go が使われる