grpc 跟常见的client-server模型相似(doubbo)
grpc 编码之前需要准备以下环境:

  • 安装protobuf,grpc的client与server之间消息传递使用的protoc格式消息,比起json,xml速度快
  • 安装grpc 的源码包

下面开始编写grpc示例代码:

  1. 首先编写proto文件,示例:helloworld
syntax = "proto3";

option objc_class_prefix = "HLW";

package helloworld;

// 定义一个Greeter服务,其中API为SayHello
// 形式参数: HelloRequest
// 返回参数:HelloReply
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {} // rpc 借口的类型分为一下四种: A为接受参数,B为返回参数
// 1. rpc GetFeature(Point) returns (Feature) {} 普通调用:A-B
// 2. rpc ListFeatures(Rectangle) returns (stream Feature) {} 单向流:A - B(流)
// 3. rpc RecordRoute(stream Point) returns (RouteSummary) {} 单向流:A(流) - B
// 4. rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} 双向流:A(流) - B(流)
} // 请求参数-根据自己的需求定义
message HelloRequest {
string name = 1;
} // 返回参数-根据自己的需求定义
message HelloReply {
string message = 1;
}

  2.  将helloworld.proto转化为helloworld.proto.go

命令:protoc --go_out=plugins=grpc:. helloworld.proto 结果如下:

// Code generated by protoc-gen-go.
// source: helloworld.proto
// DO NOT EDIT! /*
Package helloworld is a generated protocol buffer package. It is generated from these files:
helloworld.proto It has these top-level messages:
HelloRequest
HelloReply
*/
package myblogproto import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math" import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
) // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf // This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // 请求参数-根据自己的需求定义
type HelloRequest struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
} func (m *HelloRequest) Reset() { *m = HelloRequest{} }
func (m *HelloRequest) String() string { return proto.CompactTextString(m) }
func (*HelloRequest) ProtoMessage() {}
func (*HelloRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (m *HelloRequest) GetName() string {
if m != nil {
return m.Name
}
return ""
} // 返回参数-根据自己的需求定义
type HelloReply struct {
Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
} func (m *HelloReply) Reset() { *m = HelloReply{} }
func (m *HelloReply) String() string { return proto.CompactTextString(m) }
func (*HelloReply) ProtoMessage() {}
func (*HelloReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *HelloReply) GetMessage() string {
if m != nil {
return m.Message
}
return ""
} func init() {
proto.RegisterType((*HelloRequest)(nil), "helloworld.HelloRequest")
proto.RegisterType((*HelloReply)(nil), "helloworld.HelloReply")
} // Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn // This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4 // Client API for Greeter service type GreeterClient interface {
// Sends a greeting
SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
} type greeterClient struct {
cc *grpc.ClientConn
} func NewGreeterClient(cc *grpc.ClientConn) GreeterClient {
return &greeterClient{cc}
} func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {
out := new(HelloReply)
err := grpc.Invoke(ctx, "/helloworld.Greeter/SayHello", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
} // Server API for Greeter service type GreeterServer interface {
// Sends a greeting
SayHello(context.Context, *HelloRequest) (*HelloReply, error)
} func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {
s.RegisterService(&_Greeter_serviceDesc, srv)
} func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(HelloRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GreeterServer).SayHello(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/helloworld.Greeter/SayHello",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest))
}
return interceptor(ctx, in, info, handler)
} var _Greeter_serviceDesc = grpc.ServiceDesc{
ServiceName: "helloworld.Greeter",
HandlerType: (*GreeterServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "SayHello",
Handler: _Greeter_SayHello_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "helloworld.proto",
} func init() { proto.RegisterFile("helloworld.proto", fileDescriptor0) } var fileDescriptor0 = []byte{
// 149 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9,
0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x42, 0x88,
0x28, 0x29, 0x71, 0xf1, 0x78, 0x80, 0x78, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x42,
0x5c, 0x2c, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x60, 0xb6, 0x92,
0x1a, 0x17, 0x17, 0x54, 0x4d, 0x41, 0x4e, 0xa5, 0x90, 0x04, 0x17, 0x7b, 0x6e, 0x6a, 0x71, 0x71,
0x62, 0x3a, 0x4c, 0x11, 0x8c, 0x6b, 0xe4, 0xc9, 0xc5, 0xee, 0x5e, 0x94, 0x9a, 0x5a, 0x92, 0x5a,
0x24, 0x64, 0xc7, 0xc5, 0x11, 0x9c, 0x58, 0x09, 0xd6, 0x25, 0x24, 0xa1, 0x87, 0xe4, 0x02, 0x64,
0xcb, 0xa4, 0xc4, 0xb0, 0xc8, 0x14, 0xe4, 0x54, 0x2a, 0x31, 0x38, 0xb1, 0x2d, 0x62, 0x62, 0xf6,
0xf0, 0x09, 0x4f, 0x62, 0x03, 0xbb, 0xd8, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xbe, 0xde, 0x1d,
0x2e, 0xc5, 0x00, 0x00, 0x00,
}

  3. 编写grpc服务端,伪代码:

package main

import (
"fmt"
"golang.org/x/net/context"
"google.golang.org/grpc"
"net" pb "unicontract-validate/tests/grpcStudy/mybloggrpc/myblogproto"
) const port = ":50051" // 定义struct实现我们自定义的helloworld.proto对应的服务
type myServer struct {
} func (m *myServer) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{"请求server端成功!"}, nil
} /**
1. 首先我们必须实现我们自定义rpc服务,例如:rpc SayHello()-在此我们可以实现我们自己的逻辑
2. 创建监听listener
3. 创建grpc的服务
4. 将我们的服务注册到grpc的server中
5. 启动grpc服务,将我们自定义的监听信息传递给grpc服务器
*/ func main() { // 创建server端监听端口
list, err := net.Listen("tcp", port)
if err != nil {
fmt.Println(err)
} // 创建grpc的server
server := grpc.NewServer()
// 注册我们自定义的helloworld服务
pb.RegisterGreeterServer(server, &myServer{}) // 启动grpc服务
fmt.Println("grpc 服务启动... ...")
server.Serve(list)
}

  4. 编写client端代码,伪代码如下:

package main

import (
"google.golang.org/grpc"
"fmt"
"context" pb "unicontract-validate/tests/grpcStudy/mybloggrpc/myblogproto"
) // 此处应与服务器端对应
const address = "127.0.0.1:50051" /**
1. 创建groc连接器
2. 创建grpc客户端,并将连接器赋值给客户端
3. 向grpc服务端发起请求
4. 获取grpc服务端返回的结果
*/
func main() { // 创建一个grpc连接器
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil{
fmt.Println(err)
}
// 当请求完毕后记得关闭连接,否则大量连接会占用资源
defer conn.Close() // 创建grpc客户端
c := pb.NewGreeterClient(conn) name := "我是客户端,正在请求服务端!!!"
// 客户端向grpc服务端发起请求
result, err := c.SayHello(context.Background(), &pb.HelloRequest{Name:name})
fmt.Println(name)
if err != nil{
fmt.Println("请求失败!!!")
return
}
// 获取服务端返回的结果
fmt.Println(result.Message)
}

  服务端结果:

  客户端请求之后结果:

Go-GRPC 初体验的更多相关文章

  1. .NET Core 微服务之grpc 初体验(干货)

    Grpc介绍 GitHub: https://github.com/grpc/grpc gRPC是一个高性能.通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计 ...

  2. ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)

    早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把.同时记录体验的过程.如果你也想按照本文的步骤体验的话,那你得先安 ...

  3. RPC框架基础概念理解以及使用初体验

    RPC:Remote Procedure Call(远程服务调用) RPC是做什么的 通过RPC框架机器A某个进程可以通过网络调用机器B上的进程方法,就像在本地上调用一样. RPC可以基于HTTP或者 ...

  4. .NET WebSockets 核心原理初体验

    上个月我写了<.NET gRPC核心功能初体验>, 里面使用gRPC双向流做了一个打乒乓球的Demo, 实时双向这两个标签是不是很熟悉,对, WebSockets也可以做实时双向通信. 本 ...

  5. .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验

    不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...

  6. Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验

    Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...

  7. Spring之初体验

                                     Spring之初体验 Spring是一个轻量级的Java Web开发框架,以IoC(Inverse of Control 控制反转)和 ...

  8. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  9. 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...

  10. 【Knockout.js 学习体验之旅】(1)ko初体验

    前言 什么,你现在还在看knockout.js?这货都已经落后主流一千年了!赶紧去学Angular.React啊,再不赶紧的话,他们也要变out了哦.身旁的90后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...

随机推荐

  1. 代码重构--switch的惊恐现身

    switch作为条件判断(分支结构)中的一种方式,以至于我们对于它使用的频率处于较高水平的水平线上,为此我们应该使用Extra method来对这类判断条件进行抽取,另外从我自身而言,我发现我以前常常 ...

  2. nuxt 运行项目后 中总是报错

    报错的内容: nuxt.config.js中的图片 如果出现第一张图的中的错误: 请注释掉第二张图中extend里面的loader:'eslit-loader',或者把extend里面if下面的内容全 ...

  3. 浅谈new/delete和malloc/free的用法与区别

    每个程序在执行时都会占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为自由存储区或堆. 一.new和delete用法 如下几行代码: int *pi=new int; int *pi=ne ...

  4. Oracle 琐表和查询谁在琐表并解决

    Oracle数据库操作中,我们有时会用到锁表查询以及解锁和kill进程等操作,那么这些操作是怎么实现的呢?本文我们主要就介绍一下这部分内容. (1)锁表查询的代码有以下的形式: select coun ...

  5. strcat函数

    原型:char  *strcat  ( char  *dest, const  char  *src) 用法:#include  <string.h> 功能:连接两个字符串:strcat( ...

  6. C#/AutoCAD 2018/ObjectArx/二次开发添加删除实体的工具函数(四)

    1.添加删除实体 C# ObjectARX二次开发添加删除实体是非常容易主要代码如下: 添加实体: objId = btr.AppendEntity(entity); trans.AddNewlyCr ...

  7. 【R语言系列】作图入门示例一

    假设有如下数据,我们使用plot函数作图 月龄 体重 月龄 体重  1 4.4 9 7.3 3 5.3 3 6.0 5 7.2 9 10.4 2 5.2 12 10.2 11 8.5 3 6.1 R语 ...

  8. 团队作业7——第二次项目冲刺(Beta版本12.08)

    项目每个成员的进展.存在问题.接下来两天的安排. 已完成的内容:完成了排行榜的测试.上传头像功能的原型设计.界面优化 计划完成的内容:上传头像功能开发.测试.头像裁剪原型设计 每个人的工作 (有wor ...

  9. verilog学习笔记(4)_有限状态机

    有限状态机: 有限状态机是由寄存器组和组合逻辑构成的硬件时序电路: - 其状态(即由寄存器组的1和0的组合状态所构成的有限个状态)只能在同一时钟跳变沿的情况下才能从一个状态转向另一个状态: - 究竟转 ...

  10. 《高级软件测试》web测试实践--12月30日记录

    考完数学,我们正式开始web测试实践的作业,今天,我们主要进行了方案的选择和人员的分工.任务计划和安排如上图所示. 任务进展:完成题目选择和人员分工: 遇到问题:暂无: 下一步任务:完成软件评测.用户 ...