LoginSignup
0
0

GoでgRPCサーバーを立ててみる4(service.go、server.goの実装)

Posted at

お疲れ様です。

今日は「service.go、server.goの実装」について部分いたします。

service.goの実装

repositoryでやり取りしたデータをもとにgRPCのレスポンスを返すservice.goの実装をしていきます。

article/service/service.go
package service

import (
	"context"

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

type Service interface {
	CreateArticle(ctx context.Context, req *pb.CreateArticleRequest) (*pb.CreateArticleResponse, error)
	ReadArticle(ctx context.Context, req *pb.ReadArticleRequest) (*pb.ReadArticleResponse, error)
	UpdateArticle(ctx context.Context, req *pb.UpdateArticleRequest) (*pb.UpdateArticleResponse, error)
	DeleteArticle(ctx context.Context, req *pb.DeleteArticleRequest) (*pb.DeleteArticleResponse, error)
	ListArticle(req *pb.ListArticleRequest, stream pb.ArticleService_ListArticleServer) error
}

type service struct {
	repository repository.Repository
}

func NewService(r repository.Repository) Service {
	return &service{r}
}

func (s *service) CreateArticle(ctx context.Context, req *pb.CreateArticleRequest) (*pb.CreateArticleResponse, error) {
	// 記事のCREATE処理
}

func (s *service) ReadArticle(ctx context.Context, req *pb.ReadArticleRequest) (*pb.ReadArticleResponse, error) {
	// 記事のREAD処理
}

func (s *service) UpdateArticle(ctx context.Context, req *pb.UpdateArticleRequest) (*pb.UpdateArticleResponse, error) {
	// 記事のUPDATE処理
}

func (s *service) DeleteArticle(ctx context.Context, req *pb.DeleteArticleRequest) (*pb.DeleteArticleResponse, error) {
	// 記事のDELETE処理
}

func (s *service) ListArticle(req *pb.ListArticleRequest, stream pb.ArticleService_ListArticleServer) error {
	// 記事の全取得処理
}

CREATE

article/service/service.go
func (s *service) CreateArticle(ctx context.Context, req *pb.CreateArticleRequest) (*pb.CreateArticleResponse, error) {
	// INSERTする記事のInput(Author, Title, Content)を取得
	input := req.GetArticleInput()

	// 記事をDBにINSERTし、INSERTした記事のIDを返す
	id, err := s.repository.InsertArticle(ctx, input)
	if err != nil {
		return nil, err
	}

	// INSERTした記事をレスポンスとして返す
	return &pb.CreateArticleResponse{
		Article: &pb.Article{
			Id:      id,
			Author:  input.Author,
			Title:   input.Title,
			Content: input.Content,
		},
	}, nil
}

READ

article/service/service.go
func (s *service) ReadArticle(ctx context.Context, req *pb.ReadArticleRequest) (*pb.ReadArticleResponse, error) {
	// READする記事のIDを取得
	id := req.GetId()

	// DBから該当IDの記事を取得
	a, err := s.repository.SelectArticleByID(ctx, id)
	if err != nil {
		return nil, err
	}

	// 取得した記事をレスポンスとして返す
	return &pb.ReadArticleResponse{
		Article: &pb.Article{
			Id:      id,
			Author:  a.Author,
			Title:   a.Title,
			Content: a.Content,
		},
	}, nil
}

UPDATE

func (s *service) UpdateArticle(ctx context.Context, req *pb.UpdateArticleRequest) (*pb.UpdateArticleResponse, error) {
	// UPDATEする記事のIDを取得
	id := req.GetId()

	// UPDATEする記事の変更内容(Author, Title, Content)を取得
	input := req.GetArticleInput()

	// 該当IDの記事をUPDATE
	if err := s.repository.UpdateArticle(ctx, id, input); err != nil {
		return nil, err
	}

	// UPDATEした記事をレスポンスとして返す
	return &pb.UpdateArticleResponse{
		Article: &pb.Article{
			Id:      id,
			Author:  input.Author,
			Title:   input.Title,
			Content: input.Content,
		},
	}, nil
}

DELETE

article/service/service.go
func (s *service) DeleteArticle(ctx context.Context, req *pb.DeleteArticleRequest) (*pb.DeleteArticleResponse, error) {
	// DELETEする記事のIDを取得
	id := req.GetId()

	// 該当IDの記事をDELETE
	if err := s.repository.DeleteArticle(ctx, id); err != nil {
		return nil, err
	}

	// DELETEした記事のIDをレスポンスとして返す
	return &pb.DeleteArticleResponse{Id: id}, nil
}

全取得

article/service/service.go
func (s *service) ListArticle(req *pb.ListArticleRequest, stream pb.ArticleService_ListArticleServer) error {
	// 記事を全取得
	rows, err := s.repository.SelectAllArticles()
	if err != nil {
		return err
	}
	defer rows.Close()

	// 取得した記事を1つ1つレスポンスとしてServer Streamingで返す
	for rows.Next() {
		var a pb.Article
		err := rows.Scan(&a.Id, &a.Author, &a.Title, &a.Content)
		if err != nil {
			return err
		}
		stream.Send(&pb.ListArticleResponse{Article: &a})
	}
	return nil
}

これでarticleサービスの実装は完了です!

server.goの実装

gRPCサーバーを起動するserver.goの実装をしていきます。
今回gRPCサーバーはgRPCのデフォルトポートである50051に立てることにします。

article/server/server.go
package main

import (
	"log"
	"net"

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

func main() {

	// articleサーバーに接続
	lis, err := net.Listen("tcp", ":50051")
	if err != nil {
		log.Fatalf("Failed to listen: %v\n", err)
	}
	defer lis.Close()

	// Repositoryを作成
	repository, err := repository.NewsqliteRepo()
	if err != nil {
		log.Fatalf("Failed to create sqlite repository: %v\n", err)
	}
	
	// Serviceを作成
	service := service.NewService(repository)

	//サーバーにarticleサービスを登録
	server := grpc.NewServer()
	pb.RegisterArticleServiceServer(server, service)

	//articleサーバーを起動
	log.Println("Listening on port 50051...")
	if err := server.Serve(lis); err != nil {
		log.Fatalf("Failed to serve: %v", err)
	}
}

上記のようにしてarticleサービスを実装したgRPCサーバーを立てることができます。
試しに起動してみましょう。

go run article/server/server.go

起動するとDBが作成され、articleディレクトリにarticle.sqlが現れたはずです。

次はclient.goの実装をしていきましょう!

今日は以上です。

ありがとうございました。

よろしくお願いいたします。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0