entprotoでProtobusfsを生成する
EntとProtobufのスキーマは同一ではないので、entproto
がProtobufの定義(Protobufの用語では「メッセージ」と呼ばれます)を生成する方法を正確に把握できるように、スキーマにいくつかのアノテーションを付与する必要があります。
まず必要なのは、entproto.Message()
アノテーションです。 これはProtobufスキーマ生成へのオプトインです。必ずしもすべてのスキーマ・エンティティからProtoメッセージやgRPCサービス定義を生成したいわけではない場合、このアノテーションによってその制御が可能になります。 このアノテーションは、ent/schema/user.go
に追加します。
func (User) Annotations() []schema.Annotation {
return []schema.Annotation{
entproto.Message(),
}
}
次に、各フィールドにアノテーションを付けて、フィールド番号を割り当てます。 protobufメッセージタイプを定義する際、各フィールドには一意の番号を割り当てる必要があることを思い出してください。 これを行うために、各フィールドにentproto.Field
アノテーションを追加します。 ent/schema/user.go
のFields
を更新します。
// Fields of the User.
func (User) Fields() []ent.Field {
return []ent.Field{
field.String("name").
Unique().
Annotations(
entproto.Field(2),
),
field.String("email_address").
Unique().
Annotations(
entproto.Field(3),
),
}
}
数字が2から始まるのは、ent
が暗黙のうちにエンティティのID
フィールドを作成し、そのフィールドに自動的に1が割り当てられるためです。 これで、protobufメッセージタイプの定義を生成できます。 そのためには、ent/generate.go
に、entproto
コマンドラインツールを呼び出すgo:generate
ディレクティブを追加します。 以下のようになります:
package ent
//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate ./schema
//go:generate go run -mod=mod entgo.io/contrib/entproto/cmd/entproto -path ./schema
コードを再生成してみましょう:
go generate ./...
すべてのprotobuf関連の生成コードを含む新しいディレクトリが作成されたことを確認してください。ent/proto
です。 以下が含まれています:
ent/proto
└── entpb
├── entpb.proto
└── generate.go
2つのファイルが作成されました。 その内容を見てみましょう。
// Code generated by entproto. DO NOT EDIT.
syntax = "proto3";
package entpb;
option go_package = "ent-grpc-example/ent/proto/entpb";
message User {
int32 id = 1;
string user_name = 2;
string email_address = 3;
}
すばらしい! User
スキーマにマッピングするメッセージタイプ定義を含む新しい.proto
ファイルが作成されました!
package entpb
//go:generate protoc -I=.. --go_out=.. --go-grpc_out=.. --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative --entgrpc_out=.. --entgrpc_opt=paths=source_relative,schema_path=../../schema entpb/entpb.proto
新しく作成されたgenerate.go
ファイルは、.proto
ファイルから Go コードを生成する方法を指示する protobuf コードジェネレータprotoc
を呼び出します。 このコマンドを実行するためには、まずprotoc
と3つのprotobufプラグインをインストールする必要があります。protoc-gen-go
(Go Protobuf構造体を生成)、protoc-gen-go-grpc
(Go gRPCサービスインターフェースとクライアントを生成)、protoc-gen-entgrpc
(サービスインターフェースの実装を生成)です。 これらがインストールされていない場合は、以下の指示に従ってください。
protoc-gen-entgrpc
をインストールするには、以下を実行しますgo install entgo.io/contrib/entproto/cmd/protoc-gen-entgrpc@master
これらの依存関係をインストールした後、コード生成を再実行します。
go generate ./...
ent/proto/entpb/entpb.pb.go
という新しいファイルが作成され、エンティティ用に生成されたGoの構造体が含まれていることを確認してください。
このファイルを使ったテストを書いて、すべてが正しく動いていることを確認しましょう。 pb_test.go
という名前の新しいファイルを作り、以下のように書きます:
package main
import (
"testing"
"ent-grpc-example/ent/proto/entpb"
)
func TestUserProto(t *testing.T) {
user := entpb.User{
Name: "rotemtam",
EmailAddress: "rotemtam@example.com",
}
if user.GetName() != "rotemtam" {
t.Fatal("expected user name to be rotemtam")
}
if user.GetEmailAddress() != "rotemtam@example.com" {
t.Fatal("expected email address to be rotemtam@example.com")
}
}
こちらを実行してください:
go get -u ./... # install deps of the generated package
go test ./...
おめでとうございます! テストはpassしました。 Entスキーマから正しく機能するGo Protobuf構造体の生成に成功しました。 次に、スキーマから動作するCRUD gRPCサーバーを自動的に生成する方法を見てみましょう。