[Go]gRPCのAPIサーバー構築(ローカル) + コーディング規約の設定

# 1. 概要
https://qiita.com/WisteriaWave/items/907b8f8b3f2bac8ccf75

でgRPCの概要は学んだ。

が、実践で活かせるか？というとまだまだ不十分・・・・
ということで、より実践的な知見を得るため、

**イチからgRPCのAPIサーバーをローカルで構築**

をやってみた。
学習したい項目としては以下。

- **.protoのコーディング規約**: gRPCでのAPI開発における一般的なやつ
- ``.proto``ファイルから``protoc``(Goプラグイン gRPCプラグイン)によるビルドで生成される(_grpc.pb.go, pb.go)ファイル(= gRPCサービスのインターフェース定義 & リクエストパラメータのシリアライズ・デシリアライズ処理)を使った **「gRPCサービスの実装」は、具体的にはどこをどうすればいいのか？**
- **gRPCサーバーの起動に必要なmain関数への以下の記述ってどうすればいいのか？** (どんな処理をどんな流れで書けばいいの？)
    - gRPCで使うプロトコル(TCPなど)・ポート番号の記述
    - gRPCサーバーへ処理対象とするgRPCサービスを登録
    - gRPCサーバーの起動
- **gRPCサーバーを起動するにはどうしたらいいのか？**


# 2. 作成するAPIの想定と学習したい項目

**APIの想定**
以下のユースケースに沿うような「アカウント関連機能」のAPIを想定して作ってみる
- アカウント作成
- アカウント情報表示
- アカウント情報更新
- アカウント削除
- 補足
    - アカウントは「ID」・「メールアドレス」・「パスワード」をフィールドとして持つメッセージとする。
    - DBとのつなぎ込みはせず、各リクエストに対して、レスポンスフォーマットに従った固定値のレスポンスを返す形にする




---

# 3. gRPCのAPIサーバーをローカルで構築する
## 3.1. APIの設計

「2. 作成するAPIの想定と学習したい項目」で挙げた「アカウント関連機能」のAPIをgRPCで実現するにあたり、
``.proto``に記述する内容を検討する。

### 3.1.1. ``.proto``ファイルのコーディング規約

``.proto``の記述の前に、以下のGoogle公式ドキュメントを参考に、コーディング規約を定めてみた。

- [Protocol Buffers - Developer Guide - Style Guide](https://developers.google.com/protocol-buffers/docs/style)
- [Cloud APIs - API設計ガイド - 標準メソッド](https://cloud.google.com/apis/design/standard_methods?hl=ja)
- [Cloud APIs - API設計ガイド - 命名規則](https://cloud.google.com/apis/design/naming_convention?hl=ja#method_names)

注意: 
[Cloud APIs - API設計ガイド - リソース指向の設計](https://cloud.google.com/apis/design/resources)や、[Cloud Endpoints - 入門ガイド - APIの構成とデプロイ - HTTP/JSON の gRPC へのコード変換](https://cloud.google.com/endpoints/docs/grpc/transcoding)といったGoogle公式ドキュメントや、Qiita記事「[Google の protobuf で gRPC Server に REST のエンドポイントをマッピング](https://qiita.com/takat0-h0rikosh1/items/3e4c4daa0bf89f04d241)」を見るに、どうやら

- REST APIの原則的なつくりは「HTTPメソッド(POST・GET・PUT・PATCH・DELETE)」 + 「操作対象のリソース名」という形であり、リールが単純。対してRPC APIにはそのような縛りがなく、設計で混乱しやすい
- REST APIの方が広く普及している
- REST APIで送信できるデータ量はRPC APIよりも少ない
    - 動画コンテンツなどではパフォーマンス上の理由からRESTは採用されることはほとんどなくRPC APIが使われている
    - 多くの企業がデータセンター内部ではソケットベースのRPC APIを使っている

といった事情を鑑みて、「RPC と REST 双方に対応したAPIを構築する」という方針に舵を切ることを前提として、
[Cloud APIs - API設計ガイド - 標準メソッド](https://cloud.google.com/apis/design/standard_methods?hl=ja)は書かれているっぽい。

なお、RPCとREST双方に対応したAPIサーバシステムを構築する上では、
「RPC APIサーバー」の他に、以下の機能を持つ「リバースプロキシサーバー」を用意して、噛ませるというようなことをさせるらしい。
(参考: [GitHub: grpc-ecosystem/grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway))
- REST APIのリクエストをRPC APIのリクエストに変換
- RPC APIのレスポンスをREST APIのレスポンスに変換

リバースプロキシサーバーのプログラムを用意するには、以下が必要になるらしい。

- Protol Bufferコンパイラのプラグイン「gRPC-Gateway」をインストール
- ``.proto``ファイル内のサービス定義で``google.api.http``アノテーションを使用した「gRPC API」と「REST API」の紐付けを行う(「HTTPメソッド」「エンドポイントURL」「エンドポイントURLのパスパラメータ」について紐付けを行う)

この記事では、そこまですることは想定しておらず **RPC API一本でいく** ことを前提とする。

なので、「1.1.2. サービスのRPCメソッドの型定義、採用するHTTPメソッド、リクエストパラメータの受け取り方」には書いてしまったが、RPCメソッドの
- HTTPメソッド
- リクエストパラメータの受け取り方
については、``.proto``ファイルの記述する上では「無視」し、``google.api.http``アノテーションによる紐付けもしないことにした。

#### 3.1.1.1 コーディング規約 - ファイルフォーマット
参考: 

- [Protocol Buffers - スタイルガイド](https://developers.google.com/protocol-buffers/docs/style#message_and_field_names)
- [Cloud APIs - API設計ガイド - ファイル構造](https://cloud.google.com/apis/design/file_structure?hl=ja)

下記、考慮すべき項目。

---

- 1行は80文字以内
- インデントは半角スペース2つ
- 文字列はダブルクォートで囲む
- ファイル内の構成は以下の順番にする
    - コメント: 「著作権」と「ライセンス」
    - syntax文
    - package文
    - import文
    - option文
    - コメント: APIの概要
    - サービスの定義
    - メッセージの定義(リクエストとレスポンス)
        - RPCメソッド1のリクエスト
        - RPCメソッド1のレスポンス
        - RPCメソッド2のリクエスト
        - RPCメソッド2のレスポンス
        ...
    - メッセージの定義(リソース)
        - 親リソース
        - 子リソース
        ...
- 「サービス名」、「RPCメソッド名」、「メッセージタイプ名」: アッパーキャメルケース = パスカルケース(XxxXxx)
- 「メッセージのフィールド名」:  スネークケース(xxx_xxx)
- ファイル名: スネークケース

---

#### 3.1.1.2. コーディング規約 - サービスのRPCメソッドの型定義、採用するHTTPメソッド、リクエストパラメータの受け取り方
「3.1.1. .protoのコーディング規約」にも書いたが、
- HTTPメソッド
- リクエストパラメータの受け取り方
は以下に書いてしまったが、REST APIも同時実装する場合の項目なので今回、``.proto``ファイルを記述する時点で無視するものとする。


参考: 
- [Cloud APIs - 標準メソッド](https://cloud.google.com/apis/design/standard_methods)
- [Cloud APIs - 命名規則](https://cloud.google.com/apis/design/naming_convention?hl=ja#method_names)

下記、考慮すべき項目。

---

- サービスの型定義に関する命名規則・採用するHTTPメソッド・リクエストパラメータの受け取り方
    - サービス名: <リソース名>Service
    - RPCメソッド: 
        - 生成:
            - メソッド名: Create<リソース名>
            - 引数の型: Create<リソース名>Request
            - 返り値の型: <リソース名>
            - HTTPメソッド: POST
            - リクエストパラメータの受け取り方:
                - URLパス: 紐付ける親リソースの指定(``<親リソース名>s/<親リソースの識別子の値>``)
                - リクエストボディ: 生成する自身のリソース(ID、その他フィールド)
                - URLクエリパラメータ: その他の情報 
        - 表示:
            - メソッド名: Get<リソース名>
            - 引数の型: Get<リソース名>Request
            - 返り値の型: <リソース名>
            - HTTPメソッド: GET
            - リクエストパラメータの受け取り方:
                - URLパス: 表示対象の「自身のリソースを特定するための親リソースを含めたパス」(``<親リソース名>s/<親リソースの識別子の値>/<子リソース名>s/<子リソースの識別子の値>``)
                - リクエストボディ: なし
                - URLクエリパラメータ: その他の情報
        - 一覧表示:
            - メソッド名: List<リソース名>s
            - 引数の型: List<リソース名>sRequest
            - 返り値の型: List<リソース名>sResponse
            - HTTPメソッド: GET
            - リクエストパラメータの受け取り方:
                - URLパス: 表示対象の「自身のリソース群が紐づく、親のリソースを特定するためのパス」(``<親リソース名>/<親リソースの識別子の値>``)
                - リクエストボディ: なし
                - URLクエリパラメータ: その他の情報(自身のリソースの情報をいくつ取得するか？など)
        - 更新:
            - メソッド名: Update<リソース名>
            - 引数の型: Update<リソース名>Request
            - 返り値の型: <リソース名>
            - HTTPメソッド: PATCH ※完全な更新(が何を指すかはわからないが)のみとする場合はPUT。そもそも完全な更新は非推奨とのこと
            - リクエストパラメータの受け取り方:
                - URLパス: 更新対象の「自身のリソースを特定するための親リソースを含めたパス」(``<親リソース名>s/<親リソースの識別子の値>/<子リソース名>s/<子リソースの識別子の値>``)
                - リクエストボディ: (更新後の)リソース情報
                - URLクエリパラメータ: その他の情報
        - 削除:
            - メソッド名: Delete<リソース名>
            - 引数の型: Delete<リソース名>Request
            - 返り値の型: ``google.protobuf.Empty``
            - HTTPメソッド: DELETE
            - リクエストパラメータの受け取り方:
                - URLパス: 削除対象の「自身のリソースを特定するための親リソースを含めたパス」(``<親リソース名>s/<親リソースの識別子の値>/<子リソース名>s/<子リソースの識別子の値>``)
                - リクエストボディ: なし
                - URLクエリパラメータ: その他の情報

---

#### 3.1.1.3. メッセージの型定義における命名規則とフィールドの内容
参考: 
- [Cloud APIs - 標準メソッド](https://cloud.google.com/apis/design/standard_methods)
- [Cloud APIs - 命名規則](https://cloud.google.com/apis/design/naming_convention?hl=ja#method_names)


「リソース自体」「リクエストパラメータ」「レスポンスパラメータ」のメッセージの型を定義するにあたって下記、考慮すべき項目。

---
- メッセージの型
    - リソース自体の型
        - メッセージ名: <リソース名>
        - フィールド: 
            - 識別子
            - 識別子以外のリソース自体のフィールド
    - 生成
        - リクエストメッセージの型
            - メッセージ名: Create<リソース名>Request
            - フィールド:
                - 親のリソースを特定するためのパス(``<親リソース名>/<親リソースの識別子の値>``)
                - 自身のリソースの識別子
                - 自身のリソース ※リソース内のフィールドのウチ、識別子は↑で指定されたものを使う(？)
        - レスポンスメッセージの型: なし(生成したリソース自体を返し、リソース自体のメッセージの型は別途定義しているためここでは定義の必要なし)
    - 表示
        - リクエストメッセージの型
            - メッセージ名: Get<リソース名>Request
            - フィールド: 
                - 自身のリソースを特定するための親リソースを含めたパス(``<親リソース名>s/<親リソースの識別子の値>/<子リソース名>s/<子リソースの識別子の値>``)
        - レスポンスメッセージの型: なし(対象のリソース自体を返し、リソース自体のメッセージの型は別途定義しているためここでは定義の必要なし)
    - 一覧表示
        - リクエストメッセージの型
            - メッセージ名: List<リソース名>sRequest
            - フィールド: 
                - 表示対象の自身のリソース群が紐づく、親のリソースを特定するためのパス(``<親リソース名>/<親リソースの識別子の値>``)
                - 返してもらう自身のリソースの個数 など
        - レスポンスメッセージの型
            - メッセージ名: List<リソース名>sResponse
            - フィールド
                - リソースの配列
    - 更新
        - リクエストメッセージの型
            - メッセージ名: Update<リソース名>Request
            - フィールド:
                - 自身のリソース
        - レスポンスメッセージの型: なし(更新済みの対象のリソース自体を返し、リソース自体のメッセージの型は別途定義しているためここでは定義の必要なし)
    - 削除
        - リクエストメッセージの型
            - メッセージ名: Delete<リソース名>Request
            - フィールド: 自身のリソースを特定するための親リソースを含めたパス(``<親リソース名>s/<親リソースの識別子の値>/<子リソース名>s/<子リソースの識別子の値>``)
        - レスポンスメッセージの型: なし (google.protobuf.Empty を返すため、ここでは定義の必要なし)
---

### 3.1.2. 外部設計

3.1.1. で設定したコーディング規約を踏まえて、``.proto``ファイルに記述する内容を検討する。

※先述の通り、REST APIの同時実装はこの記事では考えていないため、
「サービスのインターフェース定義」について``google.api.http``アノテーションに絡む「HTTPメソッド」、「リクエストパラメータの受け取り方(URLパスパラメータ/URLクエリパラメータ/リクエストボディ)」については検討しない。
また「メッセージの定義」では、「操作対象リソースの特定のためのフィールド」は「URLパスパラメータ」を持たせるみたいなコーディング規約としていたが、こちらもgRPC API一本でいく場合は必要なく、むしろ意味がないというかそうする理由がわからん・・・となってしまうため、「リソースの識別子」を持たせることにした。

---

メモ: サービスの定義を検討するにあたっては、
リクエストパラメータ、レスポンスパラメータの型を先に決定しておかないとやりづらいな・・・・とわかったので、
「メッセージの定義 → サービスの定義の順に検討」する。


#### 3.1.2.1. 外部設計 - メッセージの定義 
(対象リソース自体のデータ構造、リクエストパラメータ、レスポンスパラメータのサーバー上でのデータ構造)

●アカウントリソース自体
- メッセージ名: Account
- メッセージのフィールド:
    - 識別子: id(string)
    - メールアドレス: email(string)
    - パスワード: password(string)

●アカウント作成API
- リクエストパラメータ
    - メッセージタイプ名: CreateAccountRequest
    - メッセージのフィールド:
        - アカウントリソース: account(Account)
- レスポンスパラメータ
    -  なし(作成した「Account」リソース自体を返すが、「Accountリソース自体」のメッセージは別途定義しているため)

●アカウント情報表示API
- リクエストパラメータ
    - メッセージタイプ名: GetAccountRequest
    - メッセージのフィールド: 
        - 識別子: id(string)
- レスポンスパラメータ
    -  なし(表示対象の「Account」リソース自体を返すが、「Accountリソース自体」のメッセージは別途定義しているため)

●アカウント情報更新API
- リクエストパラメータ
    - メッセージタイプ名: UpdateAccountRequest
    - メッセージのフィールド:
        - アカウントリソース: account(Account)
- レスポンスパラメータ
    - 　なし (更新後の「Account」リソース自体を返すが、「Accountリソース自体」のメッセージは別途定義しているため)

●アカウント削除API
- リクエストパラメータ
    - メッセージタイプ名: DeleteAccountRequest
    - メッセージのフィールド:
        - 識別子: id(string)
- レスポンスパラメータ
    - なし (google.protobuf.Empty を返すため)

#### 3.1.2.2. 外部設計 - サービスの定義

- サービス名 : AccountService
- サービス「AccountService」のRPCメソッド
    - 生成:
        - メソッド名: CreateAccount
        - 引数の型: CreateAccountRequest
        - 返り値の型: Account
    - 表示:
        - メソッド名: GetAccount
        - 引数の型: GetAccountRequest
        - 返り値の型: Account
    - 更新:
        - メソッド名: UpdateAccount
        - 引数の型: UpdateAccountRequest
        - 返り値の型: Account
    - 削除:
        - メソッド名: DeleteAccount
        - 引数の型: DeleteAccountRequest
        - 返り値の型: ``google.protobuf.Empty``

## 3.2. APIの実装
3.1.2. の外部設計を踏まえて、以下の工程を実施する。

1. ``.proto``ファイルの作成
2. ``.proto``ファイルから「gRPCサービスインターフェース定義ファイル(``_grpc.pb.go``)」と「メッセージ定義ファイル(``.pg.go``)」を生成
3. ``gRPCサービスの実装``を記述


### 3.2.0. 前準備(プロジェクト構成の決定)

``.proto``ファイルの作成しようとしたが、そもそもどこに作ればいいんや？となり、
**先にプロジェクト構成を決めておかねばならない** ことがわかった。

- **普通はモジュール化する** よね
- 「A. サービス別でディレクトリ切って``.proto``とビルド成果物の``.pb.go``を配置する」 vs **「B. ``.proto``だけのディレクトリを作る + ビルド成果物の ``.pb.go``だけのディレクトリを作る」** どっちがいいか？
    →ビルド時にビルド対象の.protoをまとめて指定しやすいB. の方がよさそう
- サービスの実装コードはサンプルだとmain.goに書かれてたけど、「APIのサービスが増えてったらmain.go内でインターフェースに対する構造体定義とそのメソッド定義が無限に爆発するよね」、ということで **「main.go と サービスの実装はファイルをわける」** のがよさそう
- **ファイル名はサービスに関わるものはその操作対象のリソース名つけとく**のが無難そう

・・・・といったことなどを踏まえ、今回は**モジュール「sample_grpc_apis」としてGitHubで公開する** ことも想定し、以下の最終形を想定することにした。

**プロジェクト構成**
```
sample_grpc_apis/
  cmd/
    api/
      main.go          # メイン処理(指定プロトコル・ポートでgRPCサーバーを起動)を記述
  pb/                  # .protoファイルからビルドしてできた成果物を格納するディレクトリ
    account.pb.go      # 「アカウント関連機能」APIのリクエストパラメータ・レスポンスパラメータのシリアライズ・デシリアライズ処理のコード
    account_grpc.pb.go # 「アカウント関連機能」APIのgRPCサービスのインターフェースコード
  proto/               # .protoファイル格納ディレクトリ
    accout.proto       # 「アカウント関連機能」APIの.protoファイル
  service/             # gRPCサービスの実装コードを格納するディレクトリ
    account_service.go # 「アカウント関連機能」APIのgRPCサービスの実装コード
  go.mod               # sample_grpc_apisモジュールの置き場、対象Goバージョン、依存先モジュールの定義
  go.sum               
  README.txt           # readme
```

モジュールの作成は[[Go]パッケージ・モジュールまとめ - 3. モジュールの作成手順](https://qiita.com/WisteriaWave/items/60a1052981131f95fbf6#3-%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%AE%E4%BD%9C%E6%88%90%E6%89%8B%E9%A0%86:~:text=3.-,%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB,-%E3%81%AE%E4%BD%9C%E6%88%90%E6%89%8B%E9%A0%86)を参考に実施する。


### 3.2.1. ``.proto``ファイルの作成

以下の内容で``.proto``ファイルを作成する

```proto/account.proto
// Protocol Buffersのバージョン指定
syntax = "proto3";

// パッケージ名(あくまでProtocol Buffersの世界でのパッケージ名であり、Goのパッケージとは無関係)
package xxxx;

// 他の.protoファイルの読み込み(ほかファイルで定義した型を使いたいときとか)
// protocコマンド実行時に指定する「--proto_path」オプションで指定するパスを基準として、相対パスで記述。
import "google/protobuf/empty.proto"; // google.protobuf.Emptyを使いたいので

// .protoファイルからビルドして生成される「メッセージ定義のソースコード」、「gRPCサービスインターフェース定義のソースコード」の出力先ディレクトリ
// protocコマンド実行時の「--go_out」オプション、「--go-grpc_out」オプションと関連する
option go_package = "pb/";

// --- サービス定義
service AccountService {
  // アカウント作成
  rpc CreateAccount (CreateAccountRequest) returns (Account) {}

  // アカウント情報表示
  rpc GetAccount (GetAccountRequest) returns (Account) {}

  // アカウント情報更新
  rpc UpdateAccount (UpdateAccountRequest) returns (Account) {}

  // アカウント削除
  rpc DeleteAccount (DeleteAccountRequest) returns (google.protobuf.Empty) {}
}


// --- メッセージ定義
// --- リクエスト & レスポンス
// [アカウント作成]リクエストメッセージ
message CreateAccountRequest {
  Account account = 1;   // 作成する「アカウント」リソース自体(ただしidは設定不要)
}

// [アカウント情報取得]リクエストメッセージ
message GetAccountRequest {
  string id = 1; // 識別子
}

// [アカウント情報更新]リクエストメッセージ
message UpdateAccountRequest {
  Account account = 1; // 更新する「アカウント」リソース自体(渡された「Account」内「id」にマッチするデータストア上の「Account」を更新)
}

// [アカウント削除]リクエストメッセージ
message DeleteAccountRequest {
  // 渡された「id」にマッチするデータストア上の「Account」を削除
  string id = 1; // 識別子
}

// リソース自体
// [アカウントリソース]
message Account {
  string id = 1;       // 識別子
  string email = 2;    // メールアドレス
  string password = 3; // パスワード
}

```

---

### 3.2.2. ``.proto``ファイルから「RPCサービスインターフェース定義ファイル(``_grpc.pb.go``)」と「メッセージ定義ファイル(``.pg.go``)」を生成

前提: 
**protocコマンドの解説**

```
protoc --go_out=<.pb.goファイル(=シリアライズ・デシリアライズ処理のコードの出力ディレクトリパス> \
       --go-grpc_out=<_grpc.pb.goファイル(=RPCメソッドのインターフェースのコード)の出力ディレクトリパス> \
       --proto_path=<.protoファイル内で別の.protoファイルをimportする時のベースパス> \
       <コンパイル対象の.protoファイルのパス>
```

メモ: 
- ``.pg.go``ファイルの出力先: ``<--go_outで指定したパス> + <.protoファイル内の「go_package」で指定したパス>``
- ``_grpc.pg.go``ファイルの出力先: ``<--go-grpc_outで指定したパス> + <.protoファイル内の「go_package」で指定したパス>``

---

以下のコマンドを実行して、``account.proto``から「RPCサービスインターフェース定義ファイル(``_grpc.pb.go``)」と「メッセージ定義ファイル(``.pb.go``)」を生成する。


```
# Goプロジェクトルートディレクトリへ移動
cd <プロジェクトルート>

# protocコマンドで``account.proto``ファイルからビルド
protoc --go_out=. --go-grpc_out=. proto/account.proto
=>pb/account.pb.go, pb/account_grpc.pb.go が出力される。
```

それぞれの中身は以下の通り

```pb/account.pb.go
// Protocol Buffersのバージョン指定

// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.28.1
// 	protoc        v3.19.3
// source: proto/account.proto

package pb

import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	emptypb "google.golang.org/protobuf/types/known/emptypb"
	reflect "reflect"
	sync "sync"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

// --- メッセージ定義
// --- リクエスト & レスポンス
// [アカウント作成]リクエストメッセージ
type CreateAccountRequest struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` // 作成する「アカウント」リソース自体(ただしidは設定不要)
}

func (x *CreateAccountRequest) Reset() {
	*x = CreateAccountRequest{}
	if protoimpl.UnsafeEnabled {
		mi := &file_proto_account_proto_msgTypes[0]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *CreateAccountRequest) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*CreateAccountRequest) ProtoMessage() {}

func (x *CreateAccountRequest) ProtoReflect() protoreflect.Message {
	mi := &file_proto_account_proto_msgTypes[0]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use CreateAccountRequest.ProtoReflect.Descriptor instead.
func (*CreateAccountRequest) Descriptor() ([]byte, []int) {
	return file_proto_account_proto_rawDescGZIP(), []int{0}
}

func (x *CreateAccountRequest) GetAccount() *Account {
	if x != nil {
		return x.Account
	}
	return nil
}

// [アカウント情報取得]リクエストメッセージ
type GetAccountRequest struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // 識別子
}

func (x *GetAccountRequest) Reset() {
	*x = GetAccountRequest{}
	if protoimpl.UnsafeEnabled {
		mi := &file_proto_account_proto_msgTypes[1]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *GetAccountRequest) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*GetAccountRequest) ProtoMessage() {}

func (x *GetAccountRequest) ProtoReflect() protoreflect.Message {
	mi := &file_proto_account_proto_msgTypes[1]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use GetAccountRequest.ProtoReflect.Descriptor instead.
func (*GetAccountRequest) Descriptor() ([]byte, []int) {
	return file_proto_account_proto_rawDescGZIP(), []int{1}
}

func (x *GetAccountRequest) GetId() string {
	if x != nil {
		return x.Id
	}
	return ""
}

// [アカウント情報更新]リクエストメッセージ
type UpdateAccountRequest struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Account *Account `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` // 更新する「アカウント」リソース自体(渡された「Account」内「id」にマッチするデータストア上の「Account」を更新)
}

func (x *UpdateAccountRequest) Reset() {
	*x = UpdateAccountRequest{}
	if protoimpl.UnsafeEnabled {
		mi := &file_proto_account_proto_msgTypes[2]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *UpdateAccountRequest) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*UpdateAccountRequest) ProtoMessage() {}

func (x *UpdateAccountRequest) ProtoReflect() protoreflect.Message {
	mi := &file_proto_account_proto_msgTypes[2]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use UpdateAccountRequest.ProtoReflect.Descriptor instead.
func (*UpdateAccountRequest) Descriptor() ([]byte, []int) {
	return file_proto_account_proto_rawDescGZIP(), []int{2}
}

func (x *UpdateAccountRequest) GetAccount() *Account {
	if x != nil {
		return x.Account
	}
	return nil
}

// [アカウント削除]リクエストメッセージ
type DeleteAccountRequest struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	// 渡された「id」にマッチするデータストア上の「Account」を削除
	Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // 識別子
}

func (x *DeleteAccountRequest) Reset() {
	*x = DeleteAccountRequest{}
	if protoimpl.UnsafeEnabled {
		mi := &file_proto_account_proto_msgTypes[3]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *DeleteAccountRequest) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*DeleteAccountRequest) ProtoMessage() {}

func (x *DeleteAccountRequest) ProtoReflect() protoreflect.Message {
	mi := &file_proto_account_proto_msgTypes[3]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use DeleteAccountRequest.ProtoReflect.Descriptor instead.
func (*DeleteAccountRequest) Descriptor() ([]byte, []int) {
	return file_proto_account_proto_rawDescGZIP(), []int{3}
}

func (x *DeleteAccountRequest) GetId() string {
	if x != nil {
		return x.Id
	}
	return ""
}

// リソース自体
// [アカウントリソース]
type Account struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Id       string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`             // 識別子
	Email    string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"`       // メールアドレス
	Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"` // パスワード
}

func (x *Account) Reset() {
	*x = Account{}
	if protoimpl.UnsafeEnabled {
		mi := &file_proto_account_proto_msgTypes[4]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *Account) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*Account) ProtoMessage() {}

func (x *Account) ProtoReflect() protoreflect.Message {
	mi := &file_proto_account_proto_msgTypes[4]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use Account.ProtoReflect.Descriptor instead.
func (*Account) Descriptor() ([]byte, []int) {
	return file_proto_account_proto_rawDescGZIP(), []int{4}
}

func (x *Account) GetId() string {
	if x != nil {
		return x.Id
	}
	return ""
}

func (x *Account) GetEmail() string {
	if x != nil {
		return x.Email
	}
	return ""
}

func (x *Account) GetPassword() string {
	if x != nil {
		return x.Password
	}
	return ""
}

var File_proto_account_proto protoreflect.FileDescriptor

var file_proto_account_proto_rawDesc = []byte{
	0x0a, 0x13, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e,
	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x78, 0x78, 0x78, 0x78, 0x1a, 0x1b, 0x67, 0x6f, 0x6f,
	0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70,
	0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3f, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61,
	0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
	0x12, 0x27, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
	0x0b, 0x32, 0x0d, 0x2e, 0x78, 0x78, 0x78, 0x78, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
	0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x23, 0x0a, 0x11, 0x47, 0x65, 0x74,
	0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e,
	0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x3f,
	0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52,
	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e,
	0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x78, 0x78, 0x78, 0x78, 0x2e, 0x41,
	0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22,
	0x26, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
	0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4b, 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75,
	0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
	0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28,
	0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73,
	0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73,
	0x77, 0x6f, 0x72, 0x64, 0x32, 0x8b, 0x02, 0x0a, 0x0e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
	0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74,
	0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x2e, 0x78, 0x78, 0x78, 0x78, 0x2e,
	0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71,
	0x75, 0x65, 0x73, 0x74, 0x1a, 0x0d, 0x2e, 0x78, 0x78, 0x78, 0x78, 0x2e, 0x41, 0x63, 0x63, 0x6f,
	0x75, 0x6e, 0x74, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f,
	0x75, 0x6e, 0x74, 0x12, 0x17, 0x2e, 0x78, 0x78, 0x78, 0x78, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63,
	0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0d, 0x2e, 0x78,
	0x78, 0x78, 0x78, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x00, 0x12, 0x3c, 0x0a,
	0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a,
	0x2e, 0x78, 0x78, 0x78, 0x78, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f,
	0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0d, 0x2e, 0x78, 0x78, 0x78,
	0x78, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0d, 0x44,
	0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x2e, 0x78,
	0x78, 0x78, 0x78, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
	0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
	0x22, 0x00, 0x42, 0x05, 0x5a, 0x03, 0x70, 0x62, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
	0x33,
}

var (
	file_proto_account_proto_rawDescOnce sync.Once
	file_proto_account_proto_rawDescData = file_proto_account_proto_rawDesc
)

func file_proto_account_proto_rawDescGZIP() []byte {
	file_proto_account_proto_rawDescOnce.Do(func() {
		file_proto_account_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_account_proto_rawDescData)
	})
	return file_proto_account_proto_rawDescData
}

var file_proto_account_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_proto_account_proto_goTypes = []interface{}{
	(*CreateAccountRequest)(nil), // 0: xxxx.CreateAccountRequest
	(*GetAccountRequest)(nil),    // 1: xxxx.GetAccountRequest
	(*UpdateAccountRequest)(nil), // 2: xxxx.UpdateAccountRequest
	(*DeleteAccountRequest)(nil), // 3: xxxx.DeleteAccountRequest
	(*Account)(nil),              // 4: xxxx.Account
	(*emptypb.Empty)(nil),        // 5: google.protobuf.Empty
}
var file_proto_account_proto_depIdxs = []int32{
	4, // 0: xxxx.CreateAccountRequest.account:type_name -> xxxx.Account
	4, // 1: xxxx.UpdateAccountRequest.account:type_name -> xxxx.Account
	0, // 2: xxxx.AccountService.CreateAccount:input_type -> xxxx.CreateAccountRequest
	1, // 3: xxxx.AccountService.GetAccount:input_type -> xxxx.GetAccountRequest
	2, // 4: xxxx.AccountService.UpdateAccount:input_type -> xxxx.UpdateAccountRequest
	3, // 5: xxxx.AccountService.DeleteAccount:input_type -> xxxx.DeleteAccountRequest
	4, // 6: xxxx.AccountService.CreateAccount:output_type -> xxxx.Account
	4, // 7: xxxx.AccountService.GetAccount:output_type -> xxxx.Account
	4, // 8: xxxx.AccountService.UpdateAccount:output_type -> xxxx.Account
	5, // 9: xxxx.AccountService.DeleteAccount:output_type -> google.protobuf.Empty
	6, // [6:10] is the sub-list for method output_type
	2, // [2:6] is the sub-list for method input_type
	2, // [2:2] is the sub-list for extension type_name
	2, // [2:2] is the sub-list for extension extendee
	0, // [0:2] is the sub-list for field type_name
}

func init() { file_proto_account_proto_init() }
func file_proto_account_proto_init() {
	if File_proto_account_proto != nil {
		return
	}
	if !protoimpl.UnsafeEnabled {
		file_proto_account_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*CreateAccountRequest); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_proto_account_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*GetAccountRequest); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_proto_account_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*UpdateAccountRequest); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_proto_account_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*DeleteAccountRequest); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_proto_account_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*Account); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: file_proto_account_proto_rawDesc,
			NumEnums:      0,
			NumMessages:   5,
			NumExtensions: 0,
			NumServices:   1,
		},
		GoTypes:           file_proto_account_proto_goTypes,
		DependencyIndexes: file_proto_account_proto_depIdxs,
		MessageInfos:      file_proto_account_proto_msgTypes,
	}.Build()
	File_proto_account_proto = out.File
	file_proto_account_proto_rawDesc = nil
	file_proto_account_proto_goTypes = nil
	file_proto_account_proto_depIdxs = nil
}

```


```pb/account_grpc.pb.go
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc             v3.19.3
// source: proto/account.proto

package pb

import (
	context "context"
	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
	emptypb "google.golang.org/protobuf/types/known/emptypb"
)

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7

// AccountServiceClient is the client API for AccountService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type AccountServiceClient interface {
	// アカウント作成
	CreateAccount(ctx context.Context, in *CreateAccountRequest, opts ...grpc.CallOption) (*Account, error)
	// アカウント情報表示
	GetAccount(ctx context.Context, in *GetAccountRequest, opts ...grpc.CallOption) (*Account, error)
	// アカウント情報更新
	UpdateAccount(ctx context.Context, in *UpdateAccountRequest, opts ...grpc.CallOption) (*Account, error)
	// アカウント削除
	DeleteAccount(ctx context.Context, in *DeleteAccountRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
}

type accountServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewAccountServiceClient(cc grpc.ClientConnInterface) AccountServiceClient {
	return &accountServiceClient{cc}
}

func (c *accountServiceClient) CreateAccount(ctx context.Context, in *CreateAccountRequest, opts ...grpc.CallOption) (*Account, error) {
	out := new(Account)
	err := c.cc.Invoke(ctx, "/xxxx.AccountService/CreateAccount", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *accountServiceClient) GetAccount(ctx context.Context, in *GetAccountRequest, opts ...grpc.CallOption) (*Account, error) {
	out := new(Account)
	err := c.cc.Invoke(ctx, "/xxxx.AccountService/GetAccount", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *accountServiceClient) UpdateAccount(ctx context.Context, in *UpdateAccountRequest, opts ...grpc.CallOption) (*Account, error) {
	out := new(Account)
	err := c.cc.Invoke(ctx, "/xxxx.AccountService/UpdateAccount", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

func (c *accountServiceClient) DeleteAccount(ctx context.Context, in *DeleteAccountRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
	out := new(emptypb.Empty)
	err := c.cc.Invoke(ctx, "/xxxx.AccountService/DeleteAccount", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// AccountServiceServer is the server API for AccountService service.
// All implementations must embed UnimplementedAccountServiceServer
// for forward compatibility
type AccountServiceServer interface {
	// アカウント作成
	CreateAccount(context.Context, *CreateAccountRequest) (*Account, error)
	// アカウント情報表示
	GetAccount(context.Context, *GetAccountRequest) (*Account, error)
	// アカウント情報更新
	UpdateAccount(context.Context, *UpdateAccountRequest) (*Account, error)
	// アカウント削除
	DeleteAccount(context.Context, *DeleteAccountRequest) (*emptypb.Empty, error)
	mustEmbedUnimplementedAccountServiceServer()
}

// UnimplementedAccountServiceServer must be embedded to have forward compatible implementations.
type UnimplementedAccountServiceServer struct {
}

func (UnimplementedAccountServiceServer) CreateAccount(context.Context, *CreateAccountRequest) (*Account, error) {
	return nil, status.Errorf(codes.Unimplemented, "method CreateAccount not implemented")
}
func (UnimplementedAccountServiceServer) GetAccount(context.Context, *GetAccountRequest) (*Account, error) {
	return nil, status.Errorf(codes.Unimplemented, "method GetAccount not implemented")
}
func (UnimplementedAccountServiceServer) UpdateAccount(context.Context, *UpdateAccountRequest) (*Account, error) {
	return nil, status.Errorf(codes.Unimplemented, "method UpdateAccount not implemented")
}
func (UnimplementedAccountServiceServer) DeleteAccount(context.Context, *DeleteAccountRequest) (*emptypb.Empty, error) {
	return nil, status.Errorf(codes.Unimplemented, "method DeleteAccount not implemented")
}
func (UnimplementedAccountServiceServer) mustEmbedUnimplementedAccountServiceServer() {}

// UnsafeAccountServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AccountServiceServer will
// result in compilation errors.
type UnsafeAccountServiceServer interface {
	mustEmbedUnimplementedAccountServiceServer()
}

func RegisterAccountServiceServer(s grpc.ServiceRegistrar, srv AccountServiceServer) {
	s.RegisterService(&AccountService_ServiceDesc, srv)
}

func _AccountService_CreateAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(CreateAccountRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(AccountServiceServer).CreateAccount(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/xxxx.AccountService/CreateAccount",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(AccountServiceServer).CreateAccount(ctx, req.(*CreateAccountRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _AccountService_GetAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(GetAccountRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(AccountServiceServer).GetAccount(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/xxxx.AccountService/GetAccount",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(AccountServiceServer).GetAccount(ctx, req.(*GetAccountRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _AccountService_UpdateAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(UpdateAccountRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(AccountServiceServer).UpdateAccount(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/xxxx.AccountService/UpdateAccount",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(AccountServiceServer).UpdateAccount(ctx, req.(*UpdateAccountRequest))
	}
	return interceptor(ctx, in, info, handler)
}

func _AccountService_DeleteAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(DeleteAccountRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(AccountServiceServer).DeleteAccount(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/xxxx.AccountService/DeleteAccount",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(AccountServiceServer).DeleteAccount(ctx, req.(*DeleteAccountRequest))
	}
	return interceptor(ctx, in, info, handler)
}

// AccountService_ServiceDesc is the grpc.ServiceDesc for AccountService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var AccountService_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "xxxx.AccountService",
	HandlerType: (*AccountServiceServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "CreateAccount",
			Handler:    _AccountService_CreateAccount_Handler,
		},
		{
			MethodName: "GetAccount",
			Handler:    _AccountService_GetAccount_Handler,
		},
		{
			MethodName: "UpdateAccount",
			Handler:    _AccountService_UpdateAccount_Handler,
		},
		{
			MethodName: "DeleteAccount",
			Handler:    _AccountService_DeleteAccount_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "proto/account.proto",
}

```

これを観察すると、以下の事実がわかる。

- ``.proto``ファイル内に記述したコメントもそのまま``.pb.go``, ``_grpc.pb.go``ファイル内に出力される
- サービス定義の変換
    - ``service XxxService`` から以下が生成されている
        -  ``type XxxServiceYyy interface`` (YyyはServer, Clientの二種類が同時生成されている) 
        -  ``type xxxServiceYyy struct`` (YyyはServer, Clientの二種類が同時生成されている)
        -  ``func NewXxxServiceYyy(cc grpc.ClientConnInterface) XxxServiceYyy
        -  ``type UnimplementedXxxServiceServer struct``
            - UnimplementedAccountServiceServer は、前方互換性のある実装を持つために埋め込む必要があります。
        - 

---

### 3.2.3. ``gRPCサービスの実装``を記述
``pb/account_grpc.pb.go``に書かれているサービス「AccountServiceServer」のインターフェースについて、``service/account_service.go``ファイルを作成し、実装していく

**インターフェース**
```pb/account_grpc.pb.go
...

// AccountServiceServer is the server API for AccountService service.
// All implementations must embed UnimplementedAccountServiceServer
// for forward compatibility
type AccountServiceServer interface {
	// アカウント作成
	CreateAccount(context.Context, *CreateAccountRequest) (*Account, error)
	// アカウント情報表示
	GetAccount(context.Context, *GetAccountRequest) (*Account, error)
	// アカウント情報更新
	UpdateAccount(context.Context, *UpdateAccountRequest) (*Account, error)
	// アカウント削除
	DeleteAccount(context.Context, *DeleteAccountRequest) (*emptypb.Empty, error)
	mustEmbedUnimplementedAccountServiceServer()
}
```


**実装**

```service/account_service.go
// アカウント関連サービスの実装

package service // serviceディレクトリにあるので・・・

import (
  "log" // 何かと使うので。
  "github.com/<オーナー名>/sample_grpc_apis/pb" // このパッケージの「AccountServiceServer」インターフェースの実装をするので。
  "google.golang.org/protobuf/types/known/emptypb"  // emptypb.Empty使うので
  "context" // context.Context使うので
)

// 以下、本質的な部分になる「account_grpc.pb.go」の「AccountServiceServer」インターフェースの実装

// -- 構造体
type AccountServiceServer struct { 
	pb.UnimplementedAccountServiceServer
}

// -- 構造体をレシーバとするメソッド
// アカウント作成
// [レシーバ] AccountServiceServerのポインタ
// [引数] 
//  ctx: ??? (Context)
//  req: アカウント作成リクエストメッセージ (CreateAccountRequestのポインタ)
// [返り値]
//  アカウントリソース (Accountのポインタ)
//  エラー (error)
func (s *AccountServiceServer) CreateAccount(ctx context.Context, req *pb.CreateAccountRequest) (*pb.Account, error) {
  log.Printf("[start]CreateAccount req: %v\n", req)

  // IDを生成
  account_id := "1"

  log.Println("[end]CreateAccount")
  return &pb.Account{ Id: account_id, Email: req.Account.Email, Password: req.Account.Password }, nil
}

// アカウント情報表示
// [レシーバ] AccountServiceServerのポインタ
// [引数] 
//  ctx: ??? (Context)
//  req: アカウント作成リクエストメッセージ (GetAccountRequestのポインタ)
// [返り値]
//  アカウントリソース (Accountのポインタ)
//  エラー (error)
func (s *AccountServiceServer) GetAccount(ctx context.Context, req *pb.GetAccountRequest) (*pb.Account, error) {
  log.Printf("[start]GetAccount req: %v\n", req)

  log.Println("[end]GetAccount")
  return &pb.Account{ Id: req.Id, Email: "test@example.com", Password: "test" }, nil
}

// アカウント情報更新
// [レシーバ] AccountServiceServerのポインタ
// [引数] 
//  ctx: ??? (Context)
//  req: アカウント作成リクエストメッセージ (UpdateAccountRequestのポインタ)
// [返り値]
//  アカウントリソース (Accountのポインタ)
//  エラー (error)
func (s *AccountServiceServer) UpdateAccount(ctx context.Context, req *pb.UpdateAccountRequest) (*pb.Account, error) {
  log.Printf("[start]UpdateAccount req: %v\n", req)

  // アカウント情報更新処理をここへ書く

  log.Println("[end]UpdateAccount")
  return &pb.Account{ Id: req.Account.Id, Email: req.Account.Email, Password: req.Account.Password }, nil
}

// アカウント削除
// [レシーバ] DeleteServiceServerのポインタ
// [引数] 
//  ctx: ??? (Context)
//  req: アカウント作成リクエストメッセージ (DeleteAccountRequestのポインタ)
// [返り値]
//  アカウントリソース (Accountのポインタ)
//  エラー (error)
func (s *AccountServiceServer) DeleteAccount(ctx context.Context, req *pb.DeleteAccountRequest) (*emptypb.Empty, error) {
  log.Printf("[start]DeleteAccount req: %v\n", req)

  // アカウント情報削除処理をここへ書く

  log.Println("[end]DeleteAccount")
  return &emptypb.Empty{}, nil
}
```

### 3.2.4. main関数にgRPCサーバーの起動処理を記述する

指定のプロトコル(TCP)・ポート(5300)でgRPCサーバーを起動するようにする。
以下のファイルを作成した。

```cmd/api/main.go
package main

import (
	"fmt"
	"log"
	"net"

  "google.golang.org/grpc"
	"google.golang.org/grpc/reflection"

	"github.com/<オーナー名>/sample_grpc_apis/pb"
	"github.com/<オーナー名>/sample_grpc_apis/service"
)

func main () {
	listenProtocol := "tcp"
	listenPortNum := 53000 // ポート番号
  
	// 1. 指定したプロトコル・ポートのListenerを作成
	// (net.Listenerが返される。Listenerとはポートに対して聞き耳を立てる人である)。
	portListener, err := net.Listen(listenProtocol, fmt.Sprintf(":%d", listenPortNum))
	// Listenに失敗したならばプログラムを即終了
	if err != nil {
		log.Fatalf("プロトコル:%v, ポート:%v のListener作成に失敗しました: %v", listenProtocol, listenPortNum, err)
	}

	// 2. gRPCサーバのインスタンスを生成
	// (grpc.Serverインスタンスのポインタが返ってくる)
	grpcServer := grpc.NewServer()

	// 3. gRPCサーバにサービスを登録
	// Register<サービス名>Server(grpc.Serverのポインタ, <サービス名>Serverのポインタ)関数は、
	// protocコマンド実行で生成された「<元になった.proroファイル名>_grpc.pb.go」内に自動で定義されている
	// ここで登録されたサービスについてのみAPIが使えるようになる
	pb.RegisterAccountServiceServer(grpcServer, &service.AccountServiceServer{})

	// 4. gRPCサーバのServer Reflectionを有効にする
	// (「grpc_cli」コマンドで、gRPCサーバに登録したサービスのRPCメソッドをシリアライズなしで実行可能になる)
	reflection.Register(grpcServer)

	// 5. gRPCサーバーを起動(指定したプロトコル・ポートのListenも開始)
	grpcServer.Serve(portListener)
}

```

### 3.2.5. 必要なモジュールをダウンロード

実装は終わったが、自動生成された*.pb.go, 作成したmain.go, account_service.goそれぞれで外部モジュールをインポートしてるので、
このままmain.goを起動しても動かず、以下のようにめちゃくちゃおこられる(当たり前)。
```
pb/account_grpc.pb.go:11:2: no required module provides package google.golang.org/grpc; to add it:
        go get google.golang.org/grpc
pb/account_grpc.pb.go:12:2: no required module provides package google.golang.org/grpc/codes; to add it:
        go get google.golang.org/grpc/codes
cmd/api/main.go:9:2: no required module provides package google.golang.org/grpc/reflection; to add it:
        go get google.golang.org/grpc/reflection
pb/account_grpc.pb.go:13:2: no required module provides package google.golang.org/grpc/status; to add it:
        go get google.golang.org/grpc/status
pb/account.pb.go:14:2: no required module provides package google.golang.org/protobuf/reflect/protoreflect; to add it:
        go get google.golang.org/protobuf/reflect/protoreflect
pb/account.pb.go:15:2: no required module provides package google.golang.org/protobuf/runtime/protoimpl; to add it:
        go get google.golang.org/protobuf/runtime/protoimpl
pb/account.pb.go:16:2: no required module provides package google.golang.org/protobuf/types/known/emptypb; to add it:
        go get google.golang.org/protobuf/types/known/emptypb
```

外部モジュールのダウンロードをする。

```
# コードをモジュール化(まだプロジェクトをモジュール化してないなら)
go mod init "github/<オーナー名>/sample_grpc/apis"

# コード内でimportしているモジュールをDL
go mod tidy
```

### 3.2.6. gRPCサーバーを起動

プロジェクトルートディレクトリで以下コマンドを実行する。

```
go run cmd/api/main.go
```

### 3.2.7. grpc_cliで実装の確認

前工程で、**main.goでgRPCサーバーに対して「server reflection」という機能をしれっと有効化** していた。
これをやっておくと、**「grpc_cli」** というコマンドラインツールを使い、クライアントからgRPCサーバーに対して以下の操作が可能になる。

- **以下の情報の取得**
    - 動作しているサービス名の一覧
    - 動作しているサービスに含まれるメソッド名、引数・返り値の型
    - 動作しているサービスに含まれるメソッドの引数や返り値の型の詳細
- **リクエストパラメータのシリアライズなしで各メソッドの動作確認**

**①grpc cliをインストールする**

以下を参考に実施。

https://public-constructor.com/mac-install-grpc_cli/#:~:text=grpc_cli%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB&text=%E3%81%BE%E3%81%9A%E3%81%AFgrpc%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92clone%E3%81%97%E3%81%BE%E3%81%99%E3%80%82&text=clone%E3%81%97%E3%81%9F%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%AB%E7%A7%BB%E5%8B%95,update%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%BE%E3%81%99%E3%80%82&text=%E3%83%93%E3%83%AB%E3%83%89%E7%94%A8%E3%81%AE%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%82%92,grpc_cli%E3%82%92%E3%83%93%E3%83%AB%E3%83%89%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

**②各メソッドの動作確認**

```
# 動作しているサービス名の表示
grpc_cli ls localhost:53000
=>
grpc.reflection.v1alpha.ServerReflection
xxxx.AccountService

# 指定したサービスのRPCメソッドを確認
grpc_cli ls localhost:53000 xxxx.AccountService -l
filename: proto/account.proto
package: xxxx;
service AccountService {
  rpc CreateAccount(xxxx.CreateAccountRequest) returns (xxxx.Account) {}
  rpc GetAccount(xxxx.GetAccountRequest) returns (xxxx.Account) {}
  rpc UpdateAccount(xxxx.UpdateAccountRequest) returns (xxxx.Account) {}
  rpc DeleteAccount(xxxx.DeleteAccountRequest) returns (google.protobuf.Empty) {}
}

# 指定したメッセージの型を確認
grpc_cli type localhost:53000 xxxx.CreateAccountRequest
message CreateAccountRequest {
  .xxxx.Account account = 1 [json_name = "account"];
}

# アカウント作成の動作確認
grpc_cli call localhost:53000 CreateAccount 'account: {id: "1", email: "test@example.com", password: "test"}'
=>
connecting to localhost:53000
id: "1"
email: "test@example.com"
password: "test"
Rpc succeeded with OK status

# アカウント情報取得の動作確認
grpc_cli call localhost:53000 GetAccount 'id: "1"'
=>
connecting to localhost:53000
id: "1"
email: "test@example.com"
password: "test"
Rpc succeeded with OK status

# アカウント情報更新の動作確認
grpc_cli call localhost:53000 UpdateAccount 'account: {id: "1", email: "test2@example.com", password: "testtest"}'
connecting to localhost:53000
id: "1"
email: "test2@example.com"
password: "testtest"
Rpc succeeded with OK status

# アカウント削除の動作確認
 grpc_cli call localhost:53000 DeleteAccount 'id: "1"'                                                    
connecting to localhost:53000
Rpc succeeded with OK status
```

# まとめ
- **.protoのコーディング規約**: gRPCでのAPI開発における一般的なやつ
  → [ここ](https://qiita.com/drafts/b7583f70ec26ac170d5a/edit#:~:text=%E3%82%92%E6%A4%9C%E8%A8%8E%E3%81%99%E3%82%8B%E3%80%82-,3.1.1,-.%20.pro%EF%BD%94o%E3%81%AE%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0)

- ``.proto``ファイルから``protoc``(Goプラグイン gRPCプラグイン)によるビルドで生成される(_grpc.pb.go, pb.go)ファイル(= gRPCサービスのインターフェース定義 & リクエストパラメータのシリアライズ・デシリアライズ処理)を使った「gRPCサービスの実装」は、具体的にはどこをどうすればいいのか？
  → [ここ](https://qiita.com/drafts/b7583f70ec26ac170d5a/edit#:~:text=3.2.3.%20gRPC-,%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9,-%E3%81%AE%E5%AE%9F%E8%A3%85%E3%82%92)
    ※シリアライズ・デシリアライズ処理の方はいい感じにやってくれるっぽく、「サービスの構造体の定義」「サービスの構造体をレシーバとするメソッドの実装」だけすればよかった。

- gRPCサーバーの起動に必要なmain関数への以下の記述ってどうすればいいのか？(どんな処理をどんな流れで書けばいいの？)
    - gRPCで使うプロトコル(TCPなど)・ポート番号の記述
    - gRPCサーバーへ処理対象とするgRPCサービスを登録
    - gRPCサーバーの起動
  → [ここ](https://qiita.com/drafts/b7583f70ec26ac170d5a/edit#:~:text=%E9%96%A2%E6%95%B0%E3%81%ABgRPC-,%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC,-%E3%81%AE%E8%B5%B7%E5%8B%95%E5%87%A6%E7%90%86)
- gRPCサーバーを起動するにはどうしたらいいのか
  → [ここ](https://qiita.com/drafts/b7583f70ec26ac170d5a/edit#:~:text=3.2.6.%20gRPC%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC-,%E3%82%92,-%E8%B5%B7%E5%8B%95)

# 参考
**.protoのコーディング規約系**

※ファイルフォーマット(XXXケース、インデント、記載順など)について

https://developers.google.com/protocol-buffers/docs/style

https://cloud.google.com/apis/design/file_structure?hl=ja

※サービス・メッセージ・メッセージとして何を内部処理・内部データとして持たせるべきか

https://cloud.google.com/apis/design/standard_methods?hl=ja

※サービス・メソッド・メッセージなどの名付けについて

https://cloud.google.com/apis/design/naming_convention?hl=ja#method_names

※↑のドキュメントへのとっかかりを作ってくれたQiita記事

https://qiita.com/tetsuya/items/e09874cfc6f189fdae79

※リクエストメッセージ・レスポンスメッセージのフィールドとして何をもたせるべきか？のサンプルに。
コメントを参照すると意図がわかりやすい

https://github.com/googleapis/googleapis/blob/ca62355cd258f9d28a8895063080393b0647eb04/google/storage/v2/storage.proto#L615

**.protocコマンド**
https://maku.blog/p/37e6uck/

**gRPC APIを実装するにあたってのプロジェクト構成**

https://dev.classmethod.jp/articles/golang-grpc-sample-project/

**google.protobuf.Emptyを使えるようにする**

https://qiita.com/Hiraku/items/7c8f56e8564158c895f9

**ポートのListen**

https://qiita.com/DQNEO/items/7027fda87a1ecf44b9f2

https://zenn.dev/hsaki/books/golang-grpc-starting/viewer/server

**gRPCのServer Reflection**

https://budougumi0617.github.io/2018/01/04/server-reflection-tutorial/

https://dev.classmethod.jp/articles/golang-grpc-sample-project/

**grpc_cliのインストール**

https://public-constructor.com/mac-install-grpc_cli/#:~:text=grpc_cli%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB&text=%E3%81%BE%E3%81%9A%E3%81%AFgrpc%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92clone%E3%81%97%E3%81%BE%E3%81%99%E3%80%82&text=clone%E3%81%97%E3%81%9F%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%AB%E7%A7%BB%E5%8B%95,update%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%BE%E3%81%99%E3%80%82&text=%E3%83%93%E3%83%AB%E3%83%89%E7%94%A8%E3%81%AE%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%82%92,grpc_cli%E3%82%92%E3%83%93%E3%83%AB%E3%83%89%E3%81%97%E3%81%BE%E3%81%99%E3%80%82