参考: https://github.com/grpc/grpc-go
http://doc.oschina.net/grpc?t=60133
快速入门 建议grpc服务分三步:写proto文件、写serve、写client
proto文件
建立文件:proto/ServeRoute.proto
syntax = "proto3";
// 指定proto版本
package proto;
// 指定包名//定义传输过程用到的数据类型,数字代表内部成员序号
message Name {
string name = 1;
}
message Msg1 {
string message = 1;
}
message Msg2 {
Msg1 message = 1;
}//定义提供的服务
service ServeRoute{
rpc Serve1(Name) returns (Msg1) {}
rpc Serve2(Name) returns (Msg2) {}
}
在proto文件所在的文件夹输入下面命令,生产pb.go文件
protoc --go_out=plugins=grpc:. ServeRoute.proto
serve文件
【go与grpc】建立serve/serve.go
package mainimport (
pb "../proto" // 引入编译生成的包
"golang.org/x/net/context"
"google.golang.org/grpc"
"log"
"net"
)
//通过一个结构体,实现proto中定义的所有服务
type ServeRoute struct{}func (h ServeRoute) Serve1(ctx context.Context, in *pb.Name) (*pb.Msg1, error) {
log.Println("serve 1 works: get name: ", in.Name)
resp := &pb.Msg1{Message:"this is serve 1"}
return resp, nil
}func (h ServeRoute) Serve2(ctx context.Context, in *pb.Name) (*pb.Msg2, error) {
log.Println("serve 2 works, get name: ", in.Name)
resp := &pb.Msg2{
Message:&pb.Msg1{Message:"this is serve 2"},
}
return resp, nil
}
func main() {
listen, err := net.Listen("tcp", "127.0.0.1:50052") // Address gRPC服务地址
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
// 与http的注册路由类似,此处将所有服务注册到grpc服务器上,
pb.RegisterServeRouteServer(s, ServeRoute{})
log.Println("grpc serve running")
if err := s.Serve(listen);
err != nil{
log.Fatal(err)
}
}
client文件
建立client/client.go(与serve分别为独立项目)
package main
import (
pb "../proto" // 引入proto包
"golang.org/x/net/context"
"google.golang.org/grpc"
"log"
)func main() {
conn, err := grpc.Dial("127.0.0.1:50052", grpc.WithInsecure())
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
c := pb.NewServeRouteClient(conn) reqBody1 := &pb.Name{Name:"wang"}
res1, err := c.Serve1(context.Background(), reqBody1)//就像调用本地函数一样,通过serve1得到返回值
if err != nil {
log.Fatalln(err)
}
log.Println("message from serve: ", res1.Message) reqBody2 := &pb.Name{Name:"li"}
res2, err := c.Serve2(context.Background(), reqBody2)//就像调用本地函数一样,通过serve2得到返回值
if err != nil {
log.Fatalln(err)
}
log.Println("message from serve: ", res2.Message.Message)
}
运行
运行serve.go之后
serve端等待请求:
2019/07/04 20:37:40 grpc serve running运行client.go之后
serve端:
2019/07/04 20:37:51 serve 1 works: get name:wang
2019/07/04 20:37:51 serve 2 works, get name:li
client端:
2019/07/04 20:37:51 message from serve:this is serve 1
2019/07/04 20:37:51 message from serve:this is serve 2
推荐阅读
- Go|Docker后端部署详解(Go+Nginx)
- GO|GO,GO,GO!
- Go成长之路|go中判断空字符串、nil和len(t)的用法
- go编译tools
- go grpc安装与使用
- goroutine 调度原理
- Go|Go进阶之路——复杂类型
- Go进阶之路——变量
- Go进阶之路——流程控制语句