Zenn
😊

Go にも“rails g scaffold”を:爆速CLIツール「gon」の紹介

に公開

Go でアプリケーションを開発していると、毎回同じようなパッケージ構造・ファイル名・初期実装を書くことに疲れてきませんか?

Rails には rails generate scaffold という便利なコマンドがあります。これがあるおかげで、開発者は構造を気にせず「まずは作る」ことに集中できます。

そんな体験を Go にも持ち込めないか?
そう思って作ったのが、CLI ツール gon です。

https://github.com/mickamy/gon


✪ gon ってなに?

gon は、Rails のように 1 コマンドで model、use-case、handler を生成できる、意見の強い Go 向けの scaffold ツールです。

gon g scaffold User name:string email:string

これを叩くだけで、以下のような構造が生成されます:

internal/
└── domain/
    └── user/
        ├── model/
        ├── repository/
        ├── usecase/
        ├── handler/
        └── fixture/

クリーンアーキテクチャに基づいた構成で、ディレクトリごとにパッケージも分けています。


✨ gon の特徴

  • Rails ライクなコマンドで爆速開発
  • model, usecase, や handler を一度に生成
  • クリーンアーキテクチャ準拠のディレクトリ構成
  • テストコードや fixture も自動で生成
  • テンプレートは embed ベースでカスタマイズ可能

🔧 インストール

Go 1.17+ なら以下でインストールできます:

go install github.com/mickamy/gon@latest

Go 1.24+ の場合は go get -tool でもOK:

go get -tool github.com/mickamy/gon

初期化とテンプレートの準備は次の 2 ステップです:

gon init     # gon.yaml を作成
gon install  # テンプレートとテストヘルパーを準備

✨ 実際に使ってみる

modle の生成

gon g model User name:string email:string

use-case の追加

gon g usecase CreateUser

handler の生成

gon g handler User list create

ぜんぶ一括で

gon g scaffold User name:string email:string

このコマンドを実行すると、以下のようなファイルが自動生成されます:

internal/
└── domain/
    └── user/
        └── fixture/
        │   └── user.go
        ├── model/
        │   └── user_model.go
        ├── usecase/
        │   ├── create_user_use_case.go
        │   ├── get_user_use_case.go
        │   ├── list_user_use_case.go
        │   ├── update_user_use_case.go
        │   └── delete_user_use_case.go
        ├── repository/
        │   └── user_repository.go
        └── handler/
            └── user_handler.go

削除もできます:

gon d scaffold User

🧱 「意見の強さ」が gon の魅力

gon は柔軟性よりも、「迷わず使える」ことを重視しています。
ディレクトリ構成や命名規則を統一することで、チーム開発でも迷子になりません。

テンプレートは embed されており、必要なら gon install 後にカスタマイズも可能です。


🧩 作成されるコードの一例

実際に作成されるコードの一部をご紹介します。

handler(ListUserHandler)

type ListUserHandler echo.HandlerFunc

func ListUser(uc usecase.ListUser) ListUserHandler {
	return func(c echo.Context) error {
		ctx := c.Request().Context()
		output, err := uc.Do(ctx, usecase.ListUserInput{})
		if err != nil {
			return c.JSON(http.StatusInternalServerError, err)
		}
		return c.JSON(http.StatusOK, output)
	}
}

usecase(CreateUser)

package usecase

import (
	"context"
)

type CreateUserInput struct {}

type CreateUserOutput struct {}

//go:generate mockgen -source=$GOFILE -destination=./mock_$GOPACKAGE/mock_$GOFILE -package=mock_$GOPACKAGE
type CreateUser interface {
	Do(ctx context.Context, input CreateUserInput) (CreateUserOutput, error)
}

type createUser struct {}

func NewCreateUser() CreateUser {
	return &createUser{}
}

func (uc createUser) Do(ctx context.Context, input CreateUserInput) (CreateUserOutput, error) {
	return CreateUserOutput{}, nil
}

repository(User)

package repository

// ...

func (repo *user) List(ctx context.Context, scopes ...func(*gorm.DB) *gorm.DB) ([]model.User, error) {
	var m []model.User
	err := repo.db.WithContext(ctx).Scopes(scopes...).Find(&m).Error
	return m, err
}
// 他のメソッドは省略

🤪 例を見てみたい?

example/ ディレクトリに、gon を使ったサンプルアプリを置いています。ぜひ覗いてみてください。


🔭 今後の展望

  • DI ライブラリへの対応
    • google/wire を想定
  • http request/response につめる DTO の生成
  • gorm/echo 以外のライブラリ対応
  • より洗練されたアーキテクチャへの改造

など、いろいろアイデアがあります。Issue や PR も歓迎しています!


🙏 最後に

gon は「Go でも Rails みたいに開発したい!」という思いから生まれました。
ぜひ試して、フィードバックをもらえると嬉しいです。

Discussion

ログインするとコメントできます