はじめに
goのパッケージ割りって悩みますよね。。
githubにもデフォルトのパッケージ割りが公開されていますが、webにそのまま使える訳でも無く、いろんな記事を見て実際に落とし込んだワイ的ベスト(現段階)パッケージ割りを紹介します!
(増田さんも「goはDDDに向かない」と仰っていましたね。。w)
TIDL(長くは無いけど)
.
├── Dockerfile
├── Makefile
├── README.md
├── bin //プロジェクトで使うバイナリ(wireとか)
├── cmd //エントリポイント
│ ├── app
│ │ ├── main.go
│ │ ├── wire.go
│ │ └── wire_gen.go
│ └── batch
│ ├── main.go
│ ├── wire.go
│ └── wire_gen.go
├── config.yaml
├── docker-compose.yaml
├── docs // ドキュメント(swaggerとか)
├── go.mod
├── go.sum
├── migrations // migrationファイル
├── pkg
│ ├── adaptor
│ │ ├── api //コントローラなどi/o(adaptor層)
│ │ │ ├── converter //i/o変換
│ │ │ ├── input //iで飛んでくるパラメータやbodyのstruct
│ │ │ ├── middleware // middleware(認証など)
│ │ ├── infrastructure
│ │ │ ├── client //APIクライアント
│ │ │ ├── dto //dto
│ │ │ └── repository //repository実装
│ │ └── logger // logger
│ ├── application //application層
│ │ ├── scenario //シナリオクラス
│ │ └── service //アプリケーションサービス
│ ├── config // config struct
│ ├── domain // domain層
│ │ ├── entity //entity
│ │ ├── factory //factoryクラス
│ │ ├── model //domain model
│ │ ├── repository // repository interface
│ │ └── service // domain service
│ ├── mock // mock(テスト用)
│ └── util //utilクラス
├── scripts //1度きりの実行スクリプト(データのimportとかに使ってます)
└── tools //module使ってるので消えない様に
bin
プロジェクトでwireだったりairだったり使うもののバイナリを置いておきます。
これでバージョン統一ができたりします。
ちなみにtoolsパッケージで定義しておきます。
https://tchssk.hatenablog.com/entry/2018/12/22/000000
cmd
goのデフォルトでもエントリポイントとして紹介されています。
プロジェクトの起動を行うmain.goを置いています。
バッチとかもあると思うので自分のプロジェクトではまとめて置いています。(実際使用する時はimageで起動コマンドを分けています)
pkg
外部に公開するパッケージです。
実際に開発する際に主に使用するパッケージです。
ちなみにinternalは外部に公開することができません
adaptor
外界との接着点です。
自分はapi/にコントローラを直置きしています。
converter
外界とアプリケーションのi/oの責務を持ちます。
パラメータやbodyで飛んできた物を変換したり、逆にentityを変換しapiレスポンスとして外界に返します。
inputとoutputパッケージを主に使用します。
input
外界から飛んでくるパラメータやbodyの定義をここで行います。(コントローラでbindして使います。)
例えばこんな感じです。
package input
type Post struct {
Title string `json:title`
Body string `json:body`
]
output
inputと同じ様にアプリケーションから外界に出ていく型を定義します。
middleware
middlewareを置きます。
infrastructure
外界との接着点で主にDBやAPIの処理を行います。
client
APIクライアントです。repositoryで使います。
dto
clientやrepositoryで使用されるdtoを定義しています。
repository
repositoryの実装クラスです。
logger
loggerですw
application
application層です。
interfaceと実装両方置いています。
scenario
シナリオクラスです。
application serviceもシナリオクラスなのですが、大きく処理が別れることがあればシナリオクラスを挟む様にしています。
シナリオクラスを爆誕させすぎるのはおすすめしないので用法容量を守って使って下さいw
service
application serviceクラスです。
例えば
type (
PostQueryService interface {
ShowPost(id int) (*entity.post, error)
}
PostQueryServiceImpl struct {
Repository repository.PostQueryRepository
}
)
余談ですが、CQRSに寄せており、controller、service、repositoryは全て_queryと_commandに分かれてます。
config
configクラスです。
どこからのパッケージでも読める様に独自にパッケージ割る様にしています
domain
domai層です
ドメイン層は説明省きます。
mock
モック置いてます。
util
utilクラス
tools