前置き
現在、Golangで開発を行っているのですが今まで使用してきたオブジェクト指向言語とは違い苦労しています。
今回は、entでメソッドチェーンするのに困ったのでどうすれば良いかを記載してたいと思います! 基本的にやり方は変わらないと思います!
環境
- golang 1.19
- ent 0.12.3
事前準備
entでは下記のような設定がされているものとします。
package schema
import (
"entgo.io/ent"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
)
// Project holds the schema definition for the Project entity.
type Project struct {
ent.Schema
}
// Mixin fields related to time.
func (Project) Mixin() []ent.Mixin {
return []ent.Mixin{
IDMixin{},
}
}
// Fields of the Project.
func (Project) Fields() []ent.Field {
return []ent.Field{
field.String("name"),
field.Time("created_at").
Immutable().
Default(time.Now),
field.Time("updated_at").
Default(time.Now).
UpdateDefault(time.Now),
field.Time("deleted_at").
Optional(),
}
}
本題
golangのレシーバーを用いて実装を行います。
レシーバーで指定している構造体のインスタンスを返却する形でメソッドチェーンを実現します!
メソッドチェーンする用のメソッドをまず定義します。
この際に注意することとしては、レシーバーを定義できるのはローカルパッケージのみのため、entの構造体ではなくProjectQueryという構造体を定義して、この中をレシーバーとして定義してあげることで*ent.ProjectQueryを使用します!
また、NewQueryを使用することで、作成を閉じ込めます。
type ProjectQuery struct {
query *ent.ProjectQuery
}
func NewQuery() *ProjectQuery {
return &ProjectQuery{
query: mysql.GetClient().Project.Query(),
}
}
func (q *ProjectQuery) WhereId(i string) *ProjectQuery {
q.query.Where(entProject.IDEQ(i))
return q
}
func (q *ProjectQuery) WhereNotDeleted() *ProjectQuery {
q.query.Where(entProject.DeletedAtIsNil())
return q
}
func (q *ProjectQuery) Only(ctx context.Context) (*ent.Project, error) {
return q.query.Only(ctx)
}
ここまで行えたらあとは呼び出すだけです。
pq := NewQuery()
p, err := a.WhereId(projectId).WhereNotDeleted().Only(ctx)
感想
個人的にこの実装を行うことで漸くレシーバになれた気がします。
また、同じメソッドがいろいろな箇所に分散していたので、漸くまとめることができるな。と一安心しました。
golangはまだまだ使い始めたばかりですが、書いているとわかりやすく書けるなと思ってきました。
これからもGoをもっと勉強していきます!