热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

go使用grpc通信示例

一.protobuf环境配置1.下载protobuf编译器protoc,下载地址: https:github.comprotocolbuffersprotobufrelease

一. protobuf环境配置

  1.下载protobuf编译器protoc, 下载地址: https://github.com/protocolbuffers/protobuf/releases

   注意根据电脑的版本下载,这里使用的是 protoc-3.19.4-win64.zip,下载完成后解压,进入bin目录中发现有一个protoc.exe二进制文件;

      将这个bin地址添加到环境变量中.

   验证安装:在cmd中输入protoc --version查看

        

  2.安装protobuf插件

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

    执行完成后在GOPATH/bin下会生成protoc-gen-go.exe和protoc-gen-go-grpc.exe文件,安装完成.

    之前版本可以通过go get命令安装.

二.编写proto文件test.proto

  protobuf文件规范参考官网.

syntax = "proto3";
option go_package = "./;pb";
package pb;
message Student {
string name = 1;
int32 age = 2;
}
message Class {
string className = 1;
}
service FindClass {
rpc MyClass(Student) returns (Class){}
}

三.通过插件生成go代码

  在test.proto中定义了一个grpc服务,在test.proto所在的目录中执行:

protoc --go_out=./ --go-grpc_out=./ test.proto

  发现在本目录下会生成两个.go文件:test.pb.go和test_grpc.pb.go,结构如下:

      

四.go文件解读

  1.test.pb.go:

    

     在test.pb.go文件中可以看到定义了两个结构体Student和Class,以及一些它们各自对应的方法,对比test.proto文件可以发现,正是我们用message关键字定义的两个消息体,而且结构体中也包含着消息体中对应的字段,其它内容感兴趣的可以自己研究.

  2.test_grpc.pb.go:

    

     FindClass是test.proto中定义的服务名称,MyClass是服务中使用的方法.

    client部分定义了一个包含MyClass方法的接口.NewFindClassClient函数用于初始化grpc的客户端,可以看到其返回正是上边定义的接口类型,这就使初始化后的客户端可以直接调用findClassClient结构体的MyClass方法.

    server部分同样也定义了一个包含MyClass方法的接口,接口中还包含了一个内部方法,此处不做分析.RegisterFindClassServer函数用于服务注册,其参数分别为一个grpc服务和一个FindClassServer接口类型.

五.grpc服务端

package main
import (
"context"
"errors"
"fmt"
"google.golang.org/grpc"
"net"
"protobuf/pb"
)
type Teacher struct {
// 由于在test_grpc.pb.go文件中FindClassServer接口不仅包含MyClass方法,还包含mustEmbedUnimplementedFindClassServer内部方法
// 所以这里直接继承 pb.FindClassServer,否则在调用注册服务时会失败
pb.FindClassServer
}
// MyClass方法接收一个上下文和一个Student对象,返回Class对象
func (t *Teacher) MyClass(ctx context.Context, stu *pb.Student) (*pb.Class, error) {
// 初始化Class对象
cla := pb.Class{}
if stu.Name == "root" && stu.Age == 3 {
cla.ClassName = "Chinese"
return &cla, nil
} else {
return &cla, errors.New("no this student")
}
}
func main() {
// 初始化一个grpc对象
service := grpc.NewServer()
// 注册服务
pb.RegisterFindClassServer(service, new(Teacher))
// 设置监听
listener, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println(err)
return
}
defer listener.Close()
//启动服务
err = service.Serve(listener)
if err != nil {
fmt.Println(err)
return
}
} 

六.grpc客户端

package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"protobuf/pb"
)
func main() {
// 连接grpc服务, 添加证书
client, err := grpc.Dial(":8080", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
fmt.Println(err)
return
}
defer client.Close()
// 初始化grpc客户端
findClassClient := pb.NewFindClassClient(client)
// findClassClient是一个包含了MyClass方法的接口类型,所以可以直接调用MyClass方法
class, err := findClassClient.MyClass(context.Background(), &pb.Student{
Name: "root",
Age: 3,
})
if err != nil {
fmt.Println(err)
return
}
fmt.Println(class.ClassName) // Chinese
} 

七.注意事项

  1. 由于版本问题,在通过proto文件生成.go文件时,之前可以通过: protoc --go_out=plugins=grpc:./ test.proto 来生成test_grpc.pb.go文件,最新版本此方法以及废弃,需要通过protoc --go-grpc_out=./ test.proto来实现;

  2.在编写服务端时,之前的版本可以直接定义一个空结构体去注册服务,但在新版本中,如果直接new一个空结构体会编译失败:

    错误如下:

      Cannot use 'new(Teacher)' (type *Teacher) as the type FindClassServerType does not implement 'FindClassServer' as some methods are missing:mustEmbedUnimplementedFindClassServer()

    可以看到是缺少mustEmbedUnimplementedFindClassServer()方法,在test_grpc.pb.go中也可以看到FindClassServer接口中确实包含了两个方法:

      

  3.如果你使用的编辑器是goland2021.3版本,会发现在test.pb.go文件中有两处标红的地方:

      

     错误信息如下:

      Cannot use 'ms' (type *messageState) as the type protoreflect.MessageType does not implement 'protoreflect.Message'need the method: ProtoMethods() *methodshave the method: ProtoMethods() *protoiface.Methods

    查了部分资料还是没得到明确的处理方法,有人说是goland2021.3的问题,不知道其他同学有没有遇到同样的问题,参考: https://github.com/grpc/grpc-go/issues/4980.

 

 



推荐阅读
  • 微服务之总体架构篇
    一、单体架构存在的问题缺点:1、难以维护:当单体应用业务不断迭代后代码量非常臃肿,模整个项目非常复杂,每次更改代码都可能带来新的bug;2、部署项目麻烦:庞大之后项目部署效率 ... [详细]
  • 基于.NET Core框架nacos的简单应用
    什么是Nacos?服务(Service)是Nacos世界的一等公民。Nacos支持 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • Nginx Buffer 机制引发的下载故障
    Nginx ... [详细]
  • Istio是一个用来连接、管理和保护微服务的开放平台。Istio提供一种简单的方式来为已部署的服务建 ... [详细]
  • 如果说以比特币为代表的货币区块链技术为1.0,以以太坊为代表的合同区块链技术为2.0,那么实现了完备的权限控制和安全保障的Hyperledger项目毫无疑问代表着区块链技术3.0 ... [详细]
  • k8s入坑之路(14)scheduler调度 kubelet管理及健康检查
    kubelet主要功能Pod管理在kubernetes的设计中,最基本的管理单位是pod,而不是container。pod是kubernetes在容器上的一层封装,由一组运行在同一 ... [详细]
author-avatar
xjq520
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有