赞
踩
安装 protobuf
https://github.com/protocolbuffers/protobuf/releases
安装golang 插件
go get -u github.com/golang/protobuf/protoc-gen-go
// 安装在 $GOPATH/bin 目录下面,记得需要把这个目录加入环境变量
放入 .zshrc
export GOPATH=$HOME/go
# 换成自己go代码的路径,这是我自己设置的路径
export GOBIN=$GOPATH/bin
# 也可以不加这一句,看自己需不需要
export PATH=$PATH:$GOPATH/bin
#把go下面的bin目录添加到电脑的环境变量中
查看版本
protoc --version
如图
服务端
package main import ( "context" "log" "net" "mygrpc/users" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ) //UserServer 实现User服务的业务对象 type UserServer struct { } //UserIndex 实现了User 服务接口的所有方法 func (u *UserServer) UserIndex(ctx context.Context, in *users.UserIndexRequest) (*users.UserIndexResponse, error) { log.Printf("receive users index request:page %d page_size %d", in.Page, in.PageSize) return &users.UserIndexResponse{ Err: 0, Msg: "success", Data: []*users.UserEntity{ {Name: "aaaa", Age: 28}, {Name: "bbbb", Age: 1}, }, }, nil } //UserView 获取详情 func (u *UserServer) UserView(ctx context.Context, in *users.UserViewRequest) (*users.UserViewResponse, error) { log.Printf("receive users uid request:uid %d", in.Uid) return &users.UserViewResponse{ Err: 0, Msg: "success", Data: &users.UserEntity{ Name: "aaaa", Age: 28, }, }, nil } //UserPost 提交数据 func (u *UserServer) UserPost(ctx context.Context, in *users.UserPostRequest) (*users.UserPostResponse, error) { log.Printf("receive users uid request:name %s password:%s,age:%d", in.Name, in.Password, in.Age) return &users.UserPostResponse{ Err: 0, Msg: "success", }, nil } //UserDelete 删除数据 func (u *UserServer) UserDelete(ctx context.Context, in *users.UserDeleteRequest) (*users.UserDeleteResponse, error) { log.Printf("receive users uid request:uid %d", in.Uid) return &users.UserDeleteResponse{ Err: 0, Msg: "success", }, nil } func main() { lis, err := net.Listen("tcp", ":1234") if err != nil { log.Fatal("failed to listen", err) } //创建rpc服务 grpcServer := grpc.NewServer() //为User服务注册业务实现 将User服务绑定到RPC服务器上 users.RegisterUserServer(grpcServer, &UserServer{}) //注册反射服务, 这个服务是CLI使用的, 跟服务本身没有关系 reflection.Register(grpcServer) if err := grpcServer.Serve(lis); err != nil { log.Fatal("faild to server,", err) } }
客户端
package main import ( "context" "fmt" "log" "mygrpc/user" "time" "google.golang.org/grpc" ) func main() { //建立链接 conn, err := grpc.Dial("127.0.0.1:1234", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatal("did not connect", err) } defer conn.Close() userClient := user.NewUserClient(conn) //设定请求超时时间 3s ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() //UserIndex 请求 userIndexResponse, err := userClient.UserIndex(ctx, &user.UserIndexRequest{ Page: 1, PageSize: 12, }) if err != nil { log.Printf("user index could not greet: %v", err) } if 0 == userIndexResponse.Err { log.Printf("user index success: %s", userIndexResponse.Msg) // 包含 UserEntity 的数组列表 userEntityList := userIndexResponse.Data for _, row := range userEntityList { fmt.Println(row.Name, row.Age) } } else { log.Printf("user index error: %d", userIndexResponse.Err) } // UserView 请求 userViewResponse, err := userClient.UserView(ctx, &user.UserViewRequest{Uid: 1}) if err != nil { log.Printf("user view could not greet: %v", err) } if 0 == userViewResponse.Err { log.Printf("user view success: %s", userViewResponse.Msg) userEntity := userViewResponse.Data fmt.Println(userEntity.Name, userEntity.Age) } else { log.Printf("user view error: %d", userViewResponse.Err) } // UserPost 请求 userPostReponse, err := userClient.UserPost(ctx, &user.UserPostRequest{Name: "big_cat", Password: "123456", Age: 29}) if err != nil { log.Printf("user post could not greet: %v", err) } if 0 == userPostReponse.Err { log.Printf("user post success: %s", userPostReponse.Msg) } else { log.Printf("user post error: %d", userPostReponse.Err) } // UserDelete 请求 userDeleteReponse, err := userClient.UserDelete(ctx, &user.UserDeleteRequest{Uid: 1}) if err != nil { log.Printf("user delete could not greet: %v", err) } if 0 == userDeleteReponse.Err { log.Printf("user delete success: %s", userDeleteReponse.Msg) } else { log.Printf("user delete error: %d", userDeleteReponse.Err) } }
user.proto
syntax = "proto3"; // user 包 package user; // 指定 go 的包路径及包名 option go_package = "./users"; // User 服务及服务接口的定义 service User { rpc UserIndex(UserIndexRequest) returns (UserIndexResponse) {} rpc UserView(UserViewRequest) returns (UserViewResponse) {} rpc UserPost(UserPostRequest) returns (UserPostResponse) {} rpc UserDelete(UserDeleteRequest) returns (UserDeleteResponse) {} } // 枚举类型 enum EnumUserSex { SEX_INIT = 0; // 枚举类型必须以 0 起始 SEX_MALE = 1; SEX_FEMALE = 2; } // 用户实体模型 message UserEntity { string name = 1; int32 age = 2; } // User 服务的各个接口的请求/响应结构 message UserIndexRequest { int32 page = 1; int32 page_size = 2; } message UserIndexResponse { int32 err = 1; string msg = 2; // 返回一个 UserEntity 对象的列表数据 repeated UserEntity data = 3; } message UserViewRequest { int32 uid = 1; } message UserViewResponse { int32 err = 1; string msg = 2; // 返回一个 UserEntity 对象 UserEntity data = 3; } message UserPostRequest { string name = 1; string password = 2; int32 age = 3; } message UserPostResponse { int32 err = 1; string msg = 2; } message UserDeleteRequest { int32 uid = 1; } message UserDeleteResponse { int32 err = 1; string msg = 2; }
protobuf 语法
syntax = "proto3"; // PB协议版本 import "google/protobuf/any.proto"; // 引用外部的message,可以是本地的,也可以是此处比较特殊的 Any package person; // 包名 option go_package = "./person_package"; // 生成类的包名,注意:会在指定路径下按照该包名的定义来生成文件夹 message PersonTest { int32 id = 1; // int 类型 string name = 2; // string 类型 string email = 3; Sex sex = 4; // 枚举类型 repeated PhoneNumber phone = 5; // 引用下面定义的 PhoneNumber 类型的 message map<string, string> tags = 6; // map 类型 repeated google.protobuf.Any details = 7; // 使用 google 的 any 类型 // 定义一个枚举 enum Sex { DEFAULT = 0; MALE = 1; Female = 2; } // 定义一个 message message PhoneNumber { string number = 1; PhoneType type = 2; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } } }
proto文件,option go_package = "./users";
,会生成 users文件夹,以及package 为 users 的包
protoc -I . users.proto --go_out=plugins=grpc:.
protoc -I . --go_out=plugins=grpc:. ./users/users.proto
protoc -I . proto.proto --go_out=plugins=grpc:.
protoc:表示调用protoc进行代码生成
-I:表示对应搜索路径(import)
. :代表当前路径
proto.proto:表示在路径下搜索的文件
--go_out=:表示生成代码格式(也可以是java_out等)
plugins=:表示对应插件这里是grpc,可以不写(protoc -I . proto.proto --go_out=:. )
:. :表示生成路径
目录
服务端:
go run server/main.go
客户端:
go run client/main.go
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。