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


関連記事

rails

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

1 はじめに2 発表について2.1 安全かつ高速に進めるマイクロサービス化2.2 Rails in Microservices2.3 MySQL/InnoDB の裏側2.4 H2O/mruby でつく ...

WebアプリからLINEのメッセージを送る方法

1 はじめに2 Messaging APIとは2.1 Messaging APIの仕組み2.2 Webhookイベント2.3 メッセージオブジェクトの種類2.4 料金形態3 LINE Develope ...

Stripe Connectを使って継続課金にクーポンを適用する

1 はじめに2 クーポンについて2.1 クーポンのタイプ2.2 期間2.3 引き換え回数制限2.4 その他3 クーポンの作成4 クーポンの使用4.1 定期支払にクーポンを適用4.2 Checkoutで ...

laravel logo

[Laravel]データベースの暗号化について考えてみる

1 はじめに2 環境3 Laravelでの暗号化4 暗号化されたカラムは、そのままではLIKE検索ができない4.1 問題点4.2 解決案1:全件取得してPHP側でがんばって検索する4.3 解決案2:暗 ...

rails

ShrineでS3に画像をアップロードする

1 はじめに1.1 前提条件1.2 関連記事2 AWS側の準備2.1 S3バケットを作成する2.2 CORSを設定する2.3 アクセス用のユーザを作成する3 Rails側の設定3.1 Initiali ...

フォロー

blog-page_side_responsive

2024年6月
 1
2345678
9101112131415
16171819202122
23242526272829
30  

アプリ情報

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