protobuf的基本类型和默认值,python中的小坑

标量数值类型

标量消息字段可以具有以下类型之一——该表显示了。原型文件,以及自动生成类中的对应类型:

默认值

python操作的坑

  1. 目录结构

  2. helloworld.proto
syntax = "proto3";

option go_package = "../proto;";

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
} message HelloRequest {
string name = 1;
repeated int32 id = 2;
} message HelloReply {
string message = 1;
}

切换到proto目录下,执行命令 python -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. helloworld.proto

3. server.py

from concurrent.futures import ThreadPoolExecutor

import grpc

from grpc_hello.proto import helloworld_pb2_grpc, helloworld_pb2

class Greeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message=f"你好, [name: {request.name}, id: {request.id}]") if __name__ == '__main__':
# 1. 实例化server
server = grpc.server(ThreadPoolExecutor(max_workers=10))
# 2. 注册逻辑到server中
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
# 3. 运行server
server.add_insecure_port("127.0.0.1:50051")
server.start()
# 主线程等待所有子线程
server.wait_for_termination()
  1. client.py
import grpc

from grpc_hello.proto import helloworld_pb2, helloworld_pb2_grpc

if __name__ == '__main__':
with grpc.insecure_channel("127.0.0.1:50051") as channel:
greeter = helloworld_pb2_grpc.GreeterStub(channel)
# 方法一:
"""
hello_request = helloworld_pb2.HelloRequest(
name="张三",
id=[1, 22, 33],
)
"""
# 方法二:
hello_request = helloworld_pb2.HelloRequest()
hello_request.name = "李四"
# 此处就是python操作时的坑所在,不能直接等于,因为创建实例时已经对id初始化了
hello_request.id.extend([11, 22, 33])
hello_request.id.append(44)
rsp: helloworld_pb2.HelloReply = greeter.SayHello(hello_request) print(rsp.message)

option go_package的作用

option go_package = "../proto;proto";

第一个分号前面的代表生成的pb文件保存的目录路径,第一个分号后面的代表包名称

当proto文件不同步的时候容易出现的问题

go的客户端和服务端

  1. client.go
点击查看代码
package main

import (
"context"
"fmt"
"goRPC/grpc_proto_test/proto"
"google.golang.org/grpc"
"log" ) func main() {
// 创建链接
clientConn, err := grpc.Dial("127.0.0.1:50053", grpc.WithInsecure())
if err != nil {
log.Fatalf("链接失败, %s\n", err.Error())
}
defer clientConn.Close()
// 声明客户端
client := proto.NewGreeterClient(clientConn)
// 客户端调用服务器的方法
helloReplay, _ := client.SayHello(context.Background(), &proto.HelloRequest{
Name: "马亚南",
Url: "mayanan.cn",
}) fmt.Println(helloReplay.Message)
}

2. server.go

点击查看代码
package main

import (
"context"
"fmt"
"goRPC/grpc_proto_test/proto"
"google.golang.org/grpc"
"log"
"net"
) type Greeter struct{} func (g *Greeter) SayHello(ctx context.Context, request *proto.HelloRequest) (*proto.HelloReply, error) {
return &proto.HelloReply{
Message: fmt.Sprintf("hello name: %s, url: %s", request.Name, request.Url),
}, nil
} func main() {
// 实例化一个server
server := grpc.NewServer() // 注册逻辑到server中
proto.RegisterGreeterServer(server, &Greeter{}) // 启动server
listener, err := net.Listen("tcp", "127.0.0.1:50053")
if err != nil {
log.Fatalln(err.Error())
}
server.Serve(listener) }

python的客户端和服务端

  1. client.py
点击查看代码
import grpc

from proto import hello_pb2, hello_pb2_grpc

if __name__ == '__main__':
# 链接server
with grpc.insecure_channel("127.0.0.1:50053") as channel:
greeter = hello_pb2_grpc.GreeterStub(channel)
rsp = greeter.SayHello(hello_pb2.HelloRequest(name="马艳娜", url="https://mayanan.cn")) print(rsp.message)
  1. server.py
点击查看代码
from concurrent.futures import ThreadPoolExecutor

import grpc

from proto import hello_pb2, hello_pb2_grpc

class Greeter(hello_pb2_grpc.GreeterServicer):
def SayHello(self, request, context):
return hello_pb2.HelloReply(message=f"hello 姓名:{request.name} url: {request.url}") if __name__ == '__main__':
# 实例化server
server = grpc.server(ThreadPoolExecutor(max_workers=10)) # 注册逻辑到server中
hello_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) # 启动server
server.add_insecure_port("127.0.0.1:50053")
server.start()
server.wait_for_termination()

proto文件中引入其它的proto文件

  1. base.proto文件
syntax = "proto3";

message Pong {
string id = 1;
}
  1. hello.proto文件
syntax = "proto3";

import "Lib/site-packages/grpc_tools/_proto/google/protobuf/empty.proto";
import "base.proto"; option go_package = "../proto;proto"; service Greeter {
rpc SayHello(HelloRequest) returns (HelloReply);
rpc Ping(google.protobuf.Empty) returns (Pong);
} message HelloRequest {
string name = 1;
string url = 2;
}
message HelloReply {
string message = 1;
}

嵌套的message对象

python中的用法

  1. base.proto
syntax = "proto3";

message Pong {
string id = 1;
}
  1. hello.proto文件
点击查看代码
syntax = "proto3";

import "google/protobuf/empty.proto";
import "base.proto"; option go_package = "../proto;proto"; service Greeter {
rpc SayHello(HelloRequest) returns (HelloReply);
rpc Ping(google.protobuf.Empty) returns (Pong);
} message HelloRequest {
string name = 1;
string url = 2;
}
message HelloReply {
string message = 1; // 嵌套的message对象
message Result {
string name = 1;
string url = 2;
} repeated Result data = 2;
}

3. server.py

点击查看代码
from concurrent.futures import ThreadPoolExecutor

import grpc

from proto import hello_pb2, hello_pb2_grpc
from google.protobuf.empty_pb2 import Empty
from proto.base_pb2 import Pong result = hello_pb2.HelloReply.Result()
pong = hello_pb2.base__pb2.Pong()
empty = hello_pb2.google_dot_protobuf_dot_empty__pb2.Empty()

go中的用法

  1. base.proto
syntax = "proto3";
option go_package = "../proto;proto"; message Empty {}
message Pong {
string id = 1;
}
  1. hello.proto
点击查看代码
syntax = "proto3";

import "base.proto";

option go_package = "../proto;proto";

service Greeter {
rpc SayHello(HelloRequest) returns (HelloReply);
rpc Ping(Empty) returns (Pong);
} message HelloRequest {
string name = 1;
string url = 2;
}
message HelloReply {
string message = 1; // 嵌套的message对象
message Result {
string name = 1;
string url = 2;
} repeated Result data = 2;
}
  1. client.go
result := proto.HelloReply_Result{}
pong := proto.Pong{}
empty := proto.Empty{}
fmt.Println(result, pong, empty)

protobuf中的enum枚举类型

  1. 枚举类型定义
enum Gender {
MALE = 0;
FEMALE = 1;
} message HelloRequest {
string name = 1;
string url = 2;
Gender g = 3;
}
  1. 枚举类型使用
	// 客户端调用服务器的方法
helloReplay, _ := client.SayHello(context.Background(), &proto_bak.HelloRequest{
Name: "马亚南",
Url: "mayanan.cn",
G: proto_bak.Gender_MALE,
})

protobuf中的map类型

  1. map类型的定义
message HelloRequest {
string name = 1;
string url = 2;
Gender g = 3;
map <string, string> mp = 4;
}
  1. map类型的使用
	// 客户端调用服务器的方法
helloReplay, _ := client.SayHello(context.Background(), &proto_bak.HelloRequest{
Name: "马亚南",
Url: "mayanan.cn",
G: proto_bak.Gender_MALE,
Mp: map[string]string{"name2": "李四", "age": "28"},
})

protobuf内置的timestamp类型

  1. 将protoc中的include目录复制到当前项目proto_bak目录下,然后导入timestamp.proto文件,定义时间戳类型
点击查看代码
syntax = "proto3";

import "include/google/protobuf/timestamp.proto";

option go_package = "../proto_bak;proto_bak";

service Greeter {
rpc SayHello(HelloRequest) returns (HelloReply);
} enum Gender {
MALE = 0;
FEMALE = 1;
} message HelloRequest {
string name = 1;
string url = 2;
Gender g = 3;
map <string, string> mp = 4;
google.protobuf.Timestamp addTime = 5;
} message HelloReply {
string message = 1;
}
  1. go代码中使用proto中的时间戳类型
点击查看代码
package main

import (
"context"
"fmt"
"goRPC/grpc_proto_test/proto_bak"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/timestamppb"
"log"
"time"
) func main() {
// 创建链接
clientConn, err := grpc.Dial("127.0.0.1:50053", grpc.WithInsecure())
if err != nil {
log.Fatalf("链接失败, %s\n", err.Error())
}
defer clientConn.Close()
// 声明客户端
client := proto_bak.NewGreeterClient(clientConn)
// 客户端调用服务器的方法
helloReplay, _ := client.SayHello(context.Background(), &proto_bak.HelloRequest{
Name: "马亚南",
Url: "mayanan.cn",
G: proto_bak.Gender_MALE,
Mp: map[string]string{"name2": "李四", "age": "28"},
AddTime: timestamppb.New(time.Now()),
}) fmt.Println(helloReplay.Message)
}

至此,protobuf大致讲解完毕。

最新文章

  1. Jquery更改table中的内容(一)
  2. 一道google面试题
  3. 0016 Java学习笔记-异常-如果try-catch-finally中都存在return语句会怎样?
  4. IOS-Gesture(手势识别)
  5. XML 命名空间
  6. python实现之极简stack和queue
  7. PHP 使用get_class_methods()和array_diff() 兩個相同的類中方法差集
  8. 【转】Android的onCreateOptionsMenu()创建菜单Menu详解
  9. ubuntu下mysql的常用命令
  10. Hadoop2.6.0 动态增加节点
  11. Mycat 安装配置
  12. PyQt中对RadioButton分组
  13. 停止预览时调用Camera.release(), 出现Method called after release()异常问题原因及解决办法
  14. 箭头函数不会修改this
  15. asp.net core 系列之用户认证(authentication)
  16. SpaceSyntax【空间句法】之DepthMapX学习:第二篇 输出了什么东西 与 核心概念
  17. application.properties 文件和 application.yml 文件的区别
  18. 关于 Uboot 中有趣的 0xdeadbeef 填充
  19. 使用JS调用手机本地摄像头或者相册图片识别二维码/条形码
  20. windows系统安装python3.6.3和python3.7.0

热门文章

  1. centos使用docker安装clickhouse
  2. JS获取当前页面的网址链接
  3. 【LeetCode】728. Self Dividing Numbers 解题报告(Python)
  4. 1742 开心的小Q
  5. 郑厂长系列故事——体检(hdu 4519)
  6. JSP、JSTL标签、EL表达式
  7. 一文搞懂Google Navigation Component
  8. 使用 windows bat 脚本命令 一键启动MySQL服务
  9. 编写Java程序,使用List集合和Map集合输出 市和区
  10. Kylin开启Kerberos安全认证