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言語の基礎〜基本構文その1〜

1 はじめに2 変数2.1 変数の定義2.2 暗黙的な定義2.3 varと暗黙的な定義2.4 ローカル変数とパッケージ変数3 定数3.1 const3.2 iota4 関数4.1 関数定義の基本4.2 ...

laravel logo

Laravel-debugerbarを使ってみた

1 はじめに2 インストール3 主な項目3.1 Messages3.2 Timeline3.3 Queries3.4 N+1 Queries3.5 Session3.6 Request4 さいごに5 ...

rails

Rails5.2+Pumaのデプロイ設定

1 はじめに1.1 環境2 Pumaとは?2.1 Unicornとの比較2.2 Pumaのスレッド3 Pumaの使い方4 デプロイ設定4.1 Gemを追加4.2 Capfileの設定4.3 deplo ...

rails

Railsで複合主キーのテーブルを扱う

1 はじめに1.1 前提条件2 実装例2.1 config2.2 マイグレーション2.3 モデル3 さいごに はじめに RailsでWebサービスを開発する際のDB設計では基本的にidが主キーになると ...

Go言語

Go 1.16でのgo getとgo installの変更点

1 はじめに2 go getとgo installの役割2.1 go getの役割2.2 go installの役割3 この変更で何が改善されたのか3.1 go:generateと併用する4 その他の ...

フォロー

blog-page_side_responsive

2024年6月
 1
2345678
9101112131415
16171819202122
23242526272829
30  

アプリ情報

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