BackEnd

GoでStructのAccessorを自動生成する

投稿日:

はじめに

DDDを採用しているとあるプロジェクトでは、structのfieldをprivateにしているため、手動で定義したGetterを介して各fieldにアクセスしています。CopilotによってGetterを生成できるとはいえ、ドメインモデルの変更に伴うfieldの変更に追従するのが面倒という課題があります。

そこで、accessorを自動生成するパッケージを使って go generate でaccessorを自動生成を試してみます。

Accessorを自動生成する

生成処理を自前で書いてもよいですが、まずはGitHubに公開されているパッケージを使って自動生成を試してみます。

今回使用するパッケージは https://github.com/masaushi/accessory です。

基本的な使い方

まず初めに、シンプルにaccessorを自動生成する方法を説明します。対象とするstructの定義は以下のとおりです。

accessorを自動生成するためには、structのfieldにaccessor tagを書く必要があります。

accessor:getter と書くと、このfieldのgetterが生成されます。同様に accessor:setter と書くと、このfieldのsetterが生成されます。

また、 getter:EmailAddress のように生成されるメソッド名を指定することもできます。

特定のfieldのaccessorを生成したくない場合は、accessor tagを書かないか、明示的に accessor:"-" と書きます。

go generate で自動生成するには、コード上に以下のように記述したうえでコマンドを実行します。

自動生成するには、typeに生成するstruct名を渡す必要があります。typeが指定されていない場合や、複数指定されている場合は生成できません。

receiver変数を変更する場合

コマンドの引数に特定のパラメータを渡すことで、自動生成の挙動をカスタマイズすることができます。

手始めに、receiver変数を指定してみます。

自動生成されたファイルでは以下のようにreceiver変数が u2 になっています。

生成するファイル名を変える場合

自動生成するファイル名を変えたい場合は、 -output で指定します。

排他制御を行い場合

accessorの排他制御を行いたい場合は、structにmutexを追加して、 -lock でfield名を指定します。

生成されたファイルは以下のとおりです。

どのように生成しているのか

DDDでの開発において、accessorのほかにも自動生成したい対象はいくつかあります。それらの自動生成を行うツールを作る参考として、このパッケージがどのようにファイルを生成しているのか、コードを見てみたいと思います。

エントリーポイント

main.go は以下のように非常にシンプルです。

cmd.Execute を実行するに当たり、引数として afero.Fsargs を渡しています。

afero.Fs は名前の通り、ファイル操作を便利にするためのパッケージのようです。

生成対象のファイルをどのように見つけているか

cmd.Execute() 関数を見てみると、以下のようになっています。

コマンドの引数に相対パスが渡されていればそのディレクトリを見に行き、渡されていなければ同一ディレクトリを見に行くようです。

structの解析

structの解析は golang.org/x/tools/go/packagespackages.Load() 関数で行っています。

その後、 *package.Packgage を自前の構造体に変換しています。

accessorを生成

accessorの生成はtemplateパッケージを使って行われます。

上記の例では、 template.TemplateParse(text string) メソッドでテンプレートファイルを読み込み、 Execute(wr io.Writer, data any) error メソッドで生成したsetterを bytes.Buffer に書き出しています。

accessorをファイル出力

ファイルへの出力では、 fmt.Fprintf()bytes.Buffer に書き込んだものを afero.WriteFile() でファイルに書き出しています。

さいごに

accessorを自動生成するパッケージの紹介と、そのパッケージがどのようにファイルを生成しているのかを調べてみました。

おすすめ書籍

初めてのGo言語 ―他言語プログラマーのためのイディオマティックGo実践ガイド Go言語 100Tips ありがちなミスを把握し、実装を最適化する impress top gearシリーズ 効率的なGo ―データ指向によるGoアプリケーションの性能最適化

blog-page_footer_336




blog-page_footer_336




-BackEnd
-

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

Go言語

Goのfmt.print系関数のまとめ

1 はじめに2 print関数の命名規則3 各print関数の説明3.1 Print(標準出力へ出力)系関数3.2 Sprint(文字列を出力)系関数3.3 Fprint(ファイルへ出力)系関数4 書 ...

rails

Rails Developer Meetup に参加してきました【2日目】

1 はじめに2 Rails Developer Meetup3 テストのないレガシーなRailsアプリをリファクタした話3.1 なぜリファクタリングしたのか3.2 コードを3種類に分類する3.3 モデ ...

Rust入門してみた その4 モジュール編

1 はじめに2 Rustのモジュール2.1 モジュールツリーの構築2.2 サブモジュール2.3 各モジュールの実装2.4 モジュールのプライバシー3 さいごに4 おすすめ書籍 はじめに これまでの記事 ...

laravel logo

Laravelのバッチ処理を作る

1 はじめに2 環境3 artisanコマンド作成4 artisanコマンドをバッチとして登録する5 さいごに6 おすすめ書籍 はじめに こんにちは。webアプリにつきもののバッチ処理ですが、もちろん ...

markdownで書けるドキュメントツールのGitbookを試す

1 はじめに2 Gitbookとは3 nvm4 node.jsインストール5 Gitbook導入5.1 インストール5.2 初期化5.3 ローカルでブラウザから確認6 作成と編集6.1 見出し編集7 ...

フォロー

blog-page_side_responsive

2024年6月
 1
2345678
9101112131415
16171819202122
23242526272829
30  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。