《go入门grpc》第六章:protoc生成的_grpc.pb.go文件解读

更方便的在微信公众号阅读文章可以关注公众号:海生的go花园
图片

一、介绍

在第五章,我们学习了.pb.go文件
《go入门grpc》第五章:protoc生成的.pb.go文件解读
本章我们学习下protoc --go-grpc_out 命令生成的_grpc.pb.go文件。
我们以hello.proto文件为例,代码如下:

syntax = "proto3";
package hello;
import "google/protobuf/timestamp.proto";

option go_package = "github/hisheng/grpc-demo1/api";

service Say {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
  google.protobuf.Timestamp last_updated = 2;
}

使用protoc --go-grpc_out命令生成了 hello_grpc.pb.go文件。

package api
......
type SayClient interface {
    SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
}
......
type SayServer interface {
    SayHello(context.Context, *HelloRequest) (*HelloReply, error)
    mustEmbedUnimplementedSayServer()
}
......

主要有三部分

  1. package
  2. Server服务端接口
  3. Client客户端接口

二、Server服务端接口

_grpc.pb.go自动生成的文件,提供了一个注册服务的方法RegisterSayServer
我们写微服务server端,是启动一个grpc服务器,然后通过RegisterSayServer方法,把 各种服务注册进去。

// SayServer 是 Say service提供api的接口
// 所有的自定义service,都必须把UnimplementedSayServer嵌入
// 才能调用SayServer接口
type SayServer interface {
    SayHello(context.Context, *HelloRequest) (*HelloReply, error)
    mustEmbedUnimplementedSayServer()
}

// UnimplementedSayServer 最原始的SayServer接口实现。
type UnimplementedSayServer struct {
}

func (UnimplementedSayServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) {
    return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented")
}
func (UnimplementedSayServer) mustEmbedUnimplementedSayServer() {}

func RegisterSayServer(s grpc.ServiceRegistrar, srv SayServer) {
    s.RegisterService(&Say_ServiceDesc, srv)
}

server 端提高了 UnimplementedSayServer,我们自己实现,这个相当于是基类。需要内嵌到我们的结构体中。

server 定义了一个对外可以使用api接口的接口SayServer
然后再生成了一个 最底层实现UnimplementedSayServer,供我们自己实现的时候,嵌入进去,然后重写其方法。
思考:

为什么要 UnimplementedSayServer ?

因为go里面,没有继承这一个 原语,我们通过嵌入的方式,实现类似的效果。
如果没有UnimplementedSayServer,那么其他的地方也写了一个 SayHello方法,但它加入是供http调用的,那么它算不算 实现了SayServer接口呢?
通过加 UnimplementedSayServer,我们知道了,它是grpc,没加就不算grpc,就很一目了然。

三、Client客户端接口

SayClient 是 SayService 的 客户端。
主要包括定义了一个SayClient接口,以及一个sayClient结构体。
sayClient结构体实现了SayClient接口。
对外提供一个 NewSayClient()来生成初始化SayClient客户端。

type SayClient interface {
   SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
}

type sayClient struct {
   cc grpc.ClientConnInterface
}

func NewSayClient(cc grpc.ClientConnInterface) SayClient {
   return &sayClient{cc}
}

func (c *sayClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {
   out := new(HelloReply)
   err := c.cc.Invoke(ctx, "/hello.Say/SayHello", in, out, opts...)
   if err != nil {
       return nil, err
   }
   return out, nil
}

与黑夜里,追求那一抹萤火。

60 声望
20 粉丝
0 条评论
推荐阅读
go语法入门-any类型的使用场景与注意
在没有any类型之前,go语言中,我们经常使用interface{},来表示一个类型是未知的,或者有好几种其他基础类型的情况。从 Go1.18开始,go官方定义了一个预声明标识符(Predeclared identifiers):any。

海生阅读 859

「刷起来」Go必看的进阶面试题详解
逃逸分析是Go语言中的一项重要优化技术,可以帮助程序减少内存分配和垃圾回收的开销,从而提高程序的性能。下面是一道涉及逃逸分析的面试题及其详解。

王中阳Go4阅读 1.9k评论 1

封面图
初学后端,如何做好表结构设计?
这篇文章介绍了设计数据库表结构应该考虑的4个方面,还有优雅设计的6个原则,举了一个例子分享了我的设计思路,为了提高性能我们也要从多方面考虑缓存问题。

王中阳Go4阅读 1.7k评论 2

封面图
滚蛋吧,正则表达式!
你是不是也有这样的操作,比如你需要使用「电子邮箱正则表达式」,首先想到的就是直接百度上搜索一个,然后采用 CV 大法神奇地接入到你的代码中?

良许4阅读 2.3k

又一款眼前一亮的Linux终端工具!
今天给大家介绍一款最近发现的功能十分强大,颜值非常高的一款终端工具。这个神器我是在其他公众号文章上看到的,但他们都没把它的强大之处介绍明白,所以我自己体验一波后,再向大家分享自己的体验。

良许5阅读 1.8k

一分钟搞明白!快速掌握 Go WebAssembly
最近因为各种奇怪的原因,更多的接触到了 WebAssembly。虽然之前很多博客也翻过写过各种文章,但总感觉欠些味道。于是今天梳理了一版,和大家一起展开学习。

煎鱼4阅读 2.2k

面试官:请说一下如何优化结构体的性能?
使用内存对齐机制优化结构体性能,妙啊!前言之前分享过2篇结构体文章:10秒改struct性能直接提升15%,产品姐姐都夸我好棒 和 Go语言空结构体这3种妙用,你知道吗? 得到了大家的好评。这篇继续分享进阶内容:结...

王中阳Go4阅读 3.8k评论 2

封面图

与黑夜里,追求那一抹萤火。

60 声望
20 粉丝
宣传栏