1、获取gRPC

环境变量GOPATH的src目录下执行:

git clone https://github.com/grpc/grpc-go.git google.golang.org/grpc

git clone https://github.com/golang/net.git golang.org/x/net

git clone https://github.com/golang/text.git golang.org/x/text

go get -u github.com/golang/protobuf/protoc-gen-go

git clone https://github.com/google/go-genproto.git google.golang.org/genproto

go install google.golang.org/grpc

 2、proto文件

gRPC 允许定义4种类型的 service 方法。

(1)编写test.proto

syntax = "proto3";
package test; //参数
message Question{
string question_str = 1;
} //返回
message Answer{
string answer_str = 1;
} //定义服务
service Test{
//简单RPC
rpc GetAnswer1(Question) returns (Answer){}
//服务端流式RPC
rpc GetAnswer2(Question) returns (stream Answer){}
//客户端流式RPC
rpc GetAnswer3(stream Question) returns (Answer){}
//双向流式RPC
rpc GetAnswer4(stream Question) returns (stream Answer){}
}

(2)生成文件test.pb.go

protoc --go_out=plugins=grpc:. test.proto

3、服务端

package main

import (
"context"
"fmt"
"io"
"log"
"net"
"test/grpc/test" "google.golang.org/grpc"
) type testServer struct{} //简单RPC
//客户端一次请求,服务端一次响应
func (*testServer) GetAnswer1(ctx context.Context, q *test.Question) (*test.Answer, error) {
answer := test.Answer{AnswerStr: fmt.Sprintf("Question:%s;Answer:%s。", q.QuestionStr, "Answer1")}
return &answer, nil
} //服务端流式RPC
//客户端一次请求,服务端多次响应
func (*testServer) GetAnswer2(q *test.Question, stream test.Test_GetAnswer2Server) error {
for i := 1; i <= 3; i++ {
answer := test.Answer{AnswerStr: fmt.Sprintf("Question:%s;Answer:%s%d。", q.QuestionStr, "Answer", i)}
if err := stream.Send(&answer); err != nil {
return err
}
}
return nil
} //客户端流式RPC
//客户端多次请求,服务端一次响应
func (*testServer) GetAnswer3(stream test.Test_GetAnswer3Server) error {
answer := test.Answer{}
for i := 1; ; i++ {
question, err := stream.Recv()
if err == io.EOF {
return stream.SendAndClose(&answer)
}
if err != nil {
return err
}
answer.AnswerStr = fmt.Sprintf("%sQuestion:%s;Answer:Answer%d。\n", answer.AnswerStr, question.QuestionStr, i)
}
} //双向流式RPC
//客户端多次请求,服务端多次响应
func (*testServer) GetAnswer4(stream test.Test_GetAnswer4Server) error {
for i := 1; ; i++ {
question, err := stream.Recv()
if err == io.EOF {
return nil
}
if err != nil {
return err
}
answer := test.Answer{AnswerStr: fmt.Sprintf("Question:%s;Answer:%s%d。", question.QuestionStr, "Answer", i)}
if err = stream.Send(&answer); err != nil {
return err
}
} } func main() {
lis, err := net.Listen("tcp", "127.0.0.1:5000")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
grpcServer := grpc.NewServer()
test.RegisterTestServer(grpcServer, &testServer{})
grpcServer.Serve(lis)
}

4、客户端

package main

import (
"context"
"fmt"
"io"
"log"
"test/grpc/test" "google.golang.org/grpc"
) func main() {
conn, err := grpc.Dial("127.0.0.1:5000", grpc.WithInsecure())
if err != nil {
log.Fatalf("fail to dial: %v", err)
}
defer conn.Close()
client := test.NewTestClient(conn) fmt.Println("简单RPC===========================")
question := test.Question{QuestionStr: "问题11111111?"}
answer, err := client.GetAnswer1(context.Background(), &question)
if err != nil {
log.Fatalf("fail to GetAnswer1: %v", err)
}
fmt.Println(answer.AnswerStr) fmt.Println("服务端流式RPC===========================")
stream, err := client.GetAnswer2(context.Background(), &question)
if err != nil {
log.Fatalf("fail to GetAnswer2: %v", err)
}
for {
answer, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("%v.GetAnswer2, %v", client, err)
}
fmt.Println(answer.AnswerStr)
} fmt.Println("客户端流式RPC===========================")
stream3, err := client.GetAnswer3(context.Background())
if err != nil {
log.Fatalf("fail to GetAnswer3: %v", err)
}
for i := 1; i <= 3; i++ {
question := test.Question{QuestionStr: fmt.Sprintf("问题%d", i)}
if err = stream3.Send(&question); err != nil {
log.Fatalf("fail to GetAnswer3 Send: %v", err)
}
}
answer, err = stream3.CloseAndRecv()
if err != nil {
log.Fatalf("fail to GetAnswer3 CloseAndRecv: %v", err)
}
fmt.Println(answer.AnswerStr) fmt.Println("双向流式RPC===============================")
done := make(chan bool)
stream4, err := client.GetAnswer4(context.Background())
if err != nil {
log.Fatalf("fail to GetAnswer4: %v", err)
}
//接受服务端响应
go func() {
for {
answer, err := stream4.Recv()
if err == io.EOF {
close(done)
return
}
if err != nil {
log.Fatalf("%v.GetAnswer4, %v", client, err)
}
fmt.Println(answer.AnswerStr)
}
}()
//客户端发送请求
for i := 1; i <= 4; i++ {
question := test.Question{QuestionStr: fmt.Sprintf("问题%d", i)}
if err = stream4.Send(&question); err != nil {
log.Fatalf("fail to GetAnswer3 Send: %v", err)
}
}
stream4.CloseSend()
<-done
}

5、输出

// 简单RPC===========================
// Question:问题11111111?;Answer:Answer1。
// 服务端流式RPC===========================
// Question:问题11111111?;Answer:Answer1。
// Question:问题11111111?;Answer:Answer2。
// Question:问题11111111?;Answer:Answer3。
// 客户端流式RPC===========================
// Question:问题1;Answer:Answer1。
// Question:问题2;Answer:Answer2。
// Question:问题3;Answer:Answer3。 // 双向流式RPC===============================
// Question:问题1;Answer:Answer1。
// Question:问题2;Answer:Answer2。
// Question:问题3;Answer:Answer3。
// Question:问题4;Answer:Answer4。

golang——gRPC学习的更多相关文章

  1. Golang gRPC学习(04): Deadlines超时限制

    为什么要使用Deadlines 当我们使用gRPC时,gRPC库关系的是连接,序列化,反序列化和超时执行.Deadlines 允许gRPC客户端设置自己等待多长时间来完成rpc操作,直到出现这个错误 ...

  2. Golang gRPC学习(03): grpc官方示例程序route_guide简析

    代码主要来源于grpc的官方examples代码: route_guide https://github.com/grpc/grpc-go/tree/master/examples/route_gui ...

  3. gRPC学习之一:在CentOS7部署和设置GO

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. gRPC学习之二:GO的gRPC开发环境准备

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos gRPC学习系列文章链接 在CentOS7部署和设置G ...

  5. gRPC学习之三:初试GO版gRPC开发

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. gRPC学习之四:实战四类服务方法

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. gRPC学习之五:gRPC-Gateway实战

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  8. Golang 语法学习笔记

    Golang 语法学习笔记 包.变量和函数. 包 每个 Go 程序都是由包组成的. 程序运行的入口是包 main. 包名与导入路径的最后一个目录一致."math/rand" 包由 ...

  9. gRPC学习

    概述 gRPC 一开始由 google 开发,是一款语言中立.平台中立.开源的远程过程调用(RPC)系统. 在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法, ...

随机推荐

  1. 【一天一个基础系列】- java之泛型篇

    简介 说起各种高级语言,不得不谈泛型,当我们在使用java集合的时候,会发现集合有个缺点:把一个对象"丢进"集合之后,集合就会"忘记"这个对象的数据类型,当再次 ...

  2. MiniSMB 网络性能测试 免费版本安装指南

    1) 烧录Image至USB 在Linux环境下可以运行以下命令(假设usb设备符号为/dev/sdb): root# tar -Jxf minismb-free-edition.img.tar.xz ...

  3. codeforces 1016C - Vasya And The Mushrooms 【构造 + 思维】

    题目链接:戳这里 题意:从(1,1)出发,一遍把格子走完,每个格子只能走一次.问怎么走总和最大. 解题思路:画图可知,总共就3种走法的混合. dw: 样例1的走法 up: 样例1反过来的走法 lp: ...

  4. HDU 6623 Minimal Power of Prime(思维)题解

    题意: 已知任意大于\(1\)的整数\(a = p_1^{q_1}p_2^{q_2} \cdots p_k^{q_k}\),现给出\(a \in [2,1e18]\),求\(min\{q_i\},q ...

  5. 美团CodeM资格赛第二题

    锦标赛 时间限制:1秒 空间限制:32768K 组委会正在为美团点评CodeM大赛的决赛设计新赛制.比赛有 n 个人参加(其中 n 为2的幂),每个参赛者根据资格赛和预赛.复赛的成绩,会有不同的积分. ...

  6. React Portal All In One

    React Portal All In One react multi root https://reactjs.org/docs/portals.html https://zh-hans.react ...

  7. how to remove duplicates of an array by using js reduce function

    how to remove duplicates of an array by using js reduce function ??? arr = ["a", ["b& ...

  8. Ajax & JSONP 原理

    Ajax & JSONP 原理 AJAX不是JavaScript的规范,它只是一个哥们"发明"的缩写:Asynchronous JavaScript and XML,意思就 ...

  9. where is the storage location of the browser's HTTP cache? disk or memory

    where is the storage location of the browser's HTTP cache? disk or memory HTTP cache & storage l ...

  10. Flutter: MediaQuery

    Flutter Widget of the Week 使用MediaQuery根据不同的屏幕大小调整应用程序的UI布局. 您还可以使用它根据用户布局首选项进行UI调整. class _MyHomeSt ...