go grpc(protobuf) 简单使用教程

go gprc 使用 教程

技术栈

grpc
go
protobuff

1.环境

1.1. 安装protoc

项目地址 https://github.com/protocolbuffers/protobuf

下载protobuff, 有条件的github上直接下载,github下载地址,或者可以从maven仓库下载

在maven仓库中找到对应的版本,进行下载,linux ,windows 都有

1589089027209.png

这里我下载 windows 64 位的这个

下载下来的是可执行文件,直接放到环境变量里面,这个文件名太长了,把后缀都去掉

我放的路径 %GOPATH%\bin\protoc.exe

1.2. 安装 protoc-gen-go

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

go get 的比较慢的话可以用代理。需要配置下代理。

看下 %GOPATH%\bin\ 有没有protoc-gen-go.exe ,没有的话需要找到下载的包进行安装。

下载目录在:%GOPATH%\pkg\mod\github.com\golang\protobuf@xxx\protoc-gen-go

进入目录然后 go install ,然后再去看bin 目录就会生成protoc-gen-go.exe

1589090845985.png

2. 建项目实践

1. 建目录 grpcprj

go mod init grpcprj

这个是我创建后的目录

|   go.mod #工程文件
|   go.sum #工程文件
+---client #客户端代码存放目录
|       main.go 
+---proto #proto 文件存放目录,包括通过protoc 编译后的文件
|   \---hello
|           hello.pb.go #protoc 根据proto文件生成的go项目文件
|           hello.proto #proto 文件
\---server #服务端代码
    |   main.go
    \---handler #服务端接口实现
            hello.go
2. 编写proto文件
syntax="proto3"; //版本

package go.rpc.srv.hello; //作用域

service Hello{ //service 表示服务,在这里面定义接口
 //定义了一个接口SayHello 接收了一个Say消息,返回一个Say消息
 rpc SayHello(Say) returns (Say);  
}

// 定义一个结构体,Say
message Say {
string name = 1; // 定义格式如下 :<修饰符> 类型 字段名 = 唯一编号

//由于一些历史原因,基本数值类型的repeated的字段并没有被尽可能地高效编码。
//在新的代码中,用户应该使用特殊选项[packed=true]来保证更高效的编码。
//注意[packed=true]只能用在 repeated修饰的数字类型中
//repeated用来定义数组
repeated  int32 list =2; //repeated 

//定义map
map<string, string> maps = 3;

//有时候你需要保留一些你以后要用到的编号或者变量名,使用reserved关键字
reserved 3, 15, 9 to 11; //保留 3,15,9到11
reserved "foo", "bar";

//string var2 = 3;//编译会报错,因为3被保留了
//string var3 = 10;//编译会报错,因为10被保留了
//string foo = 12;//编译会报错,因为foo被保留了
}

消息体可以嵌套,也可以引入其他的proto文件

import "google/protobuf/any.proto"; //引入其他文件

//消息嵌套
message ParentBean{
    ChildA child = 1;
    message ChildB{
        string name = 1;
    } 
    ChildB child2 = 2 ;
}
message ChildA{
    string name = 1;
}

字段类型对比

.proto Type Go Type 说明
double float64
float float32
int32 int32 使用变长编码,对于负值的效率很低,如果你的域有可能有负值,请使用sint64替代
uint32 uint32 使用变长编码
uint64 uint64 使用变长编码
sint32 int32 使用变长编码,这些编码在负值时比int32高效的多
sint64 int64 使用变长编码,有符号的整型值。编码时比通常的int64高效。
fixed32 uint32 总是4个字节,如果数值总是比总是比228大的话,这个类型会比uint32高效。
fixed64 uint64 总是8个字节,如果数值总是比总是比256大的话,这个类型会比uint64高效。
sfixed32 int32 总是4个字节
sfixed64 int64 总是8个字节
bool bool 默认 false
string string 一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本,默认值为空。
bytes []byte 默认是空数组
3. 编译proto文件

​ proto 文件编写完毕以后,使用protoc 进行编译,编译成成 xxx.pb.go,编译是干什么呢?

protoc --go_out=plugins=grpc:. proto/hello/hello.proto

​ 运行命令后会在 proto 文件同目录生成 xxx.pb.go,对应的service 会成生成一个空的实现(指的是只做了实现,并没有具体业务功能),这里需要注意的是,默认go环境变量已经配置正确,gopath\bin 在环境变量里面。

hello.proto(最简的)

syntax="proto3";

service Hello{
    rpc SyaHello(Say) returns (Say);
}

message Say {
  string name = 1;
}

编译后的文件

...省略了其他代码
// HelloServer is the server API for Hello service.
// helloServer 接口
type HelloServer interface { 
    SyaHello(context.Context, *Say) (*Say, error)
}

// UnimplementedHelloServer can be embedded to have forward compatible implementations.

type UnimplementedHelloServer struct {
}

// 以下是一个空的实现,没有实现任何业务逻辑
func (*UnimplementedHelloServer) SyaHello(context.Context, *Say) (*Say, error) {
    return nil, status.Errorf(codes.Unimplemented, "method SyaHello not implemented")
}
4. 实现服务端接口逻辑

​ 服务端可以实现,也可以不实现,也可以改下上面的默认生成的这个实现类,这里重新实现了下,里面写自己的业务逻辑。

server/handler/hello.go(最简实现)

package handler

import (
    "context"
    "fmt"
    h "grpcprj/proto/hello"
    )

type HelloImpl struct {}

func (hi *HelloImpl)SyaHello(ctx context.Context,in *h.Say) (*h.Say, error){
    msg:=fmt.Sprintf("echo say:%s",in.GetName())
    return &h.Say{Name:msg},nil
}
5. 服务端代码
package main

import (
 "context"
 "google.golang.org/grpc"
 h "grpcprj/proto/hello"
 "log"
 "time"
)

var(
 addr  ="localhost:8081"
 defmsg = "hello boger"
)

func main()  {

 var(
     conn *grpc.ClientConn
     ctx context.Context
     cancel context.CancelFunc
     err error
     r *h.Say
 )

 if conn,err=grpc.Dial(addr,grpc.WithInsecure(),grpc.WithBlock());err!=nil{
     log.Fatalf("conn server err :%v",err)
 }
 defer conn.Close()
 c := h.NewHelloClient(conn)

 ctx,cancel=context.WithTimeout(context.Background(),time.Second)
 defer cancel()
 if r,err=c.SyaHello(ctx,&h.Say{Name:defmsg});err!=nil{
     log.Fatalf("get error :%v",err)
 }
 log.Printf("get msg :%s",r.Name)
}
6. 客户端代码

​ protoc 生成的go 代码里面包括服务端的定义,和客户端的定义(协议的打包,解包都包括了)

​ grpcprj/client/hello.go

package main

import (
    "context"
    "google.golang.org/grpc"
    h "grpcprj/proto/hello"
    "log"
    "time"
)

var(
    addr  ="localhost:8081"
    defmsg = "hello boger"
)

func main()  {

    var(
        conn *grpc.ClientConn
        ctx context.Context
        cancel context.CancelFunc
        err error
        r *h.Say
    )

    if conn,err=grpc.Dial(addr,grpc.WithInsecure(),grpc.WithBlock());err!=nil{
        log.Fatalf("conn server err :%v",err)
    }
    defer conn.Close()
    c := h.NewHelloClient(conn)

    ctx,cancel=context.WithTimeout(context.Background(),time.Second)
    defer cancel()
    if r,err=c.SyaHello(ctx,&h.Say{Name:defmsg});err!=nil{
        log.Fatalf("get error :%v",err)
    }
    log.Printf("get msg :%s",r.Name)
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,978评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,954评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,623评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,324评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,390评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,741评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,892评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,655评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,104评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,569评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,254评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,834评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,725评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,950评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,260评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,446评论 2 348