本节将带您体验基于 go 语言创建一套完整的 gRPC 应用。
本节以一个文章服务为例,为您演示 grpc 的完整实现流程。
请提前安装相关工具包
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
如 : D:\grpcDemo,然后初始化 go mod :
go mod init grpcdemo
文件位置 : /项目根目录/pbfiles/article.proto
编辑如下代码
syntax = "proto3";
option go_package = "../services";
// 定义Article服务
service Article {
// 定义方法
rpc GetInfo (ArticleRequest) returns (ArticleReply) {}
// 可以定义多个方法
}
// 请求数据结构
message ArticleRequest {
int32 Id = 1;
}
// 响应数据结构
message ArticleReply {
int32 Id = 1;
string Title = 2;
string Content = 3;
}
执行如下命令 :
cd .\pbfiles
protoc --go_out=../services --go_opt=paths=source_relative --go-grpc_out=../services --go-grpc_opt=paths=source_relative ./article.proto
cd ../
go mod tidy
在项目根目录下创建 service.go , 编写如下代码 :
package main
import (
"context"
"flag"
"fmt"
"grpcdemo/services"
"log"
"net"
"google.golang.org/grpc"
)
var (
port = flag.Int("port", 8008, "The server port")
)
// 定义服务主体
type server struct {
services.UnimplementedArticleServer
}
// 实现获取文章接口
func (s *server) GetInfo(ctx context.Context, in *services.ArticleRequest) (*services.ArticleReply, error) {
log.Printf("Received: %v", in.GetId())
return &services.ArticleReply{
Id: in.GetId(),
Title: "grpc",
Content: "grpc is a good framework",
}, nil
}
func main() {
flag.Parse()
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
services.RegisterArticleServer(s, &server{})
log.Printf("server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
go run service.go
## ... server listening at [::]:8008
文件 :./client_test.go
package main
import (
"context"
"grpcdemo/services"
"testing"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestGetInfo(t *testing.T) {
conn, err := grpc.Dial("localhost:8008", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
t.Fatal(err)
}
defer conn.Close()
// 调用服务
client := services.NewArticleClient(conn)
res, err := client.GetInfo(context.Background(), &services.ArticleRequest{Id: 1})
if err != nil {
t.Fatal(err)
}
t.Log(res)
}
go test -v -run TestGetInfo
=== RUN TestGetInfo
client_test.go:25: Id:1 Title:"grpc" Content:"grpc is a good framework"
--- PASS: TestGetInfo (0.01s)
PASS