GoでgRPCサーバーを立ててみる5（client.goの実装、動作確認）

お疲れ様です。

今日は「client.goの実装、動作確認」について部分いたします。

# client.goの実装

gRPCサーバーとやり取りするclient.goの実装をしていきます。

```article/client/client.go
package client

import (
	"context"
	"io"

	"github.com/k88t76/GraphQL-gRPC-demo/article/pb"
	"github.com/k88t76/GraphQL-gRPC-demo/graph/model"
	"google.golang.org/grpc"
)

// Clientからサービスを呼び出せるようにする
type Client struct {
	conn    *grpc.ClientConn
	Service pb.ArticleServiceClient
}

func NewClient(url string) (*Client, error) {
	// client connectionを生成
	conn, err := grpc.Dial(url, grpc.WithInsecure())
	if err != nil {
		return nil, err
	}

	// articleサービスのclientを生成
	c := pb.NewArticleServiceClient(conn)
	
	// articleサービスのclientを返す
	return &Client{conn, c}, nil
}
```

これでclientの生成ができるようになりました。

# 動作確認

動作確認のためにarticleディレクトリ配下にmain.goを作成します。

```
.
└─ article
|  ├── client ─ client.go
|  ├── pb ─ article.pb.go 
|  ├── repository ─ repository.go
|  ├── server ─ server.go
|  ├── service - service.go
|  ├── article.proto
|  ├── article.sql
|  └── main.go (動作確認用)
├── go.mod
└── go.sum
```

main.go内でclientを生成し、5つの動作確認を行なっていきます。

```article/main.go
package main

import (
	"context"
	"fmt"
	"io"
	"log"

	"github.com/k88t76/GraphQL-gRPC-demo/article/client"
	"github.com/k88t76/GraphQL-gRPC-demo/article/pb"
)

// gRPCサーバーの動作確認用
func main() {
	// clientを生成
	c, _ := client.NewClient("localhost:50051")
	
	create(c)
	read(c)
	update(c)
	delete(c)
	list(c)
}

func create(c *client.Client) {
	// 記事をCREATE
}

func read(c *client.Client) {
	// 記事をREAD
}

func update(c *client.Client) {
	// 記事をUPDATE
}

func delete(c *client.Client) {
	// 記事をDELETE
}

func list(c *client.Client) {
	// 記事を全取得
}
```

## CREATE

```article/main.go
func create(c *client.Client) {
	// 記事をCREATE
	input := &pb.ArticleInput{
		Author:  "gopher",
		Title:   "gRPC",
		Content: "gRPC is so cool!",
	}
	res, err := c.Service.CreateArticle(context.Background(), &pb.CreateArticleRequest{ArticleInput: input})
	if err != nil {
		log.Fatalf("Failed to CreateArticle: %v\n", err)
	}
	fmt.Printf("CreateArticle Response: %v\n", res)
}
```

以下のコマンドを実行すると、Responseが返ってくると思います。

```terminal
go run article/main.go
>>> CreateArticle Response: article:{id:1  author:"gopher"  title:"gRPC"  content:"gRPC is so cool!"}
```

実際にデータベースに保存されているかどうかは以下のコマンドで確認できます。

```
sqlite3 article/article.sql

(上記コマンド実行後)
sqlite> select * from articles;

>>> 1|gopher|gRPC|gRPC is so cool!
```

いくつかCREATEした後、他の動きも試してみましょう。

## READ
```article/main.go
func read(c *client.Client) {
	// 記事をREAD
	var id int64 = 2
	res, err := c.Service.ReadArticle(context.Background(), &pb.ReadArticleRequest{Id: id})
	if err != nil {
		log.Fatalf("Failed to ReadArticle: %v\n", err)
	}
	fmt.Printf("ReadArticle Response: %v\n", res)
}
```

```terminal
>>> ReadArticle Response: article:{id:2  author:"gopher"  title:"gRPC-2"  content:"gRPC is so awesome!"}
```

## UPDATE

```article/main.go
func update(c *client.Client) {
	// 記事をUPDATE
	var id int64 = 2
	input := &pb.ArticleInput{
		Author:  "GraphQL master",
		Title:   "GraphQL",
		Content: "GraphQL is very smart!",
	}
	res, err := c.Service.UpdateArticle(context.Background(), &pb.UpdateArticleRequest{Id: id, ArticleInput: input})
	if err != nil {
		log.Fatalf("Failed to UpdateArticle: %v\n", err)
	}
	fmt.Printf("UpdateArticle Response: %v\n", res)
}
```

```terminal
>>> UpdateArticle Response: article:{id:2 author:"GraphQL master" title:"GraphQL" content:"GraphQL is very smart!"}
```

## DELETE

```article/main.go
func delete(c *client.Client) {
	// 記事をDELETE
	var id int64 = 1
	res, err := c.Service.DeleteArticle(context.Background(), &pb.DeleteArticleRequest{Id: id})
	if err != nil {
		log.Fatalf("Failed to UpdateArticle: %v\n", err)
	}
	fmt.Printf("The article has been deleted (%v)\n", res)
}
```

```terminal
>>> The article has been deleted (id:1)
```

## 全取得

```article/main.go
func list(c *client.Client) {
	// streamレスポンスを受け取る
	stream, err := c.Service.ListArticle(context.Background(), &pb.ListArticleRequest{})
	if err != nil {
		log.Fatalf("Failed to ListArticle: %v\n", err)
	}
	
	// Server Streamingで渡されたレスポンスを１つ１つ出力
	for {
		res, err := stream.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("Failed to Server Streaming: %v\n", err)
		}
		fmt.Println(res)
	}
}
```

```terminal
>>> article:{id:2  author:"GraphQL master"  title:"GraphQL"  content:"GraphQL is very smart!"}
article:{id:3  author:"gopher3"  title:"gRPC-3"  content:"gRPC is so nice!"}
article:{id:4  author:"gopher4"  title:"poyo"  content:"gRPC is poyopoyo"}
article:{id:5  author:"gopher5"  title:"go"  content:"go go golang!"}
```

以上でgRPCサーバーの実装が完了しました！
動作確認ができたらarticle配下のmain.goはこれ以降使わないので、削除してもらって大丈夫です。

# おわりに

「GoでgRPCサーバーを立ててみる」については以上です。
長くなりましたが、ここまで読んでいただき誠にありがとうございます!

今日は以上です。
ありがとうございました。
よろしくお願いいたします。