go: 获取grpc extension

2022-11-29 17:14:32 浏览数 (1)

最近在接入交换机上报数据的时候,收到一个比较少见的proto文件telemetry_top.proto。字段定义成了extension。

代码语言:javascript复制
message TelemetryStream { 
 //.... 
  optional EnterpriseSensors enterprise = 101; 
} 
extend EnterpriseSensors { 
 // re-use IANA assigned numbers 
  optional JuniperNetworksSensors juniperNetworks = 2636; 
} 
message JuniperNetworksSensors { extensions 1 to max; } 

enterprise的格式是EnterpriseSensors,是一个extend格式。EnterpriseSensors中又有一个JuniperNetworksSensors,它也是一个extension。

找到具体实现的proto,同时编译

首先这样的格式,一定会有一个实体的承载,这里的telemetry_top.proto类似是基类/抽象类,找到那个实体类,将它编译到同一个package中。 需求方提供的实体类,在这个项目中是port.proto

代码语言:javascript复制
syntax = "proto2";
import "telemetry_top.proto"; // 注意这里
option go_package = "xxx/proto/juniper/telemetrytop";
//
// This occupies branch 3 from JuniperNetworksSensors
//
extend JuniperNetworksSensors { optional Port jnpr_interface_ext = 3; }
//
// Top-level message
//
message Port { repeated InterfaceInfos interface_stats = 1; }
// ...........

同时,将telemetry_top.proto也指定相同的go_package。

telemetry_top.proto

代码语言:javascript复制
syntax = "proto2"; 
option go_package = "xxx/proto/juniper/telemetrytop"; 
import "google/protobuf/descriptor.proto"; 

然后使用protoc 编译port.proto

获取数据

代码语言:javascript复制
// parser top 
pb := &telemetrytop.TelemetryStream{} 
err = proto.Unmarshal(body, pb) 
if err != nil { 
 return 
} 
// 从解出的Proto中获取字段,使用proto.GetExtension方式 
data := proto.GetExtension(pb.Enterprise, telemetrytop.E_JuniperNetworks) 
// 因为是双重的extension,所以再解一次 
networks, ok := data.(*telemetrytop.JuniperNetworksSensors) 
if !ok { 
    err = fmt.Errorf("get network extension failed, data type is :%v", reflect.TypeOf(data)) 
 return 
} 
// 终于解到了正确的实体类 
portExt := proto.GetExtension(networks, telemetrytop.E_JnprInterfaceExt) 
_, ok = portExt.(*telemetrytop.Port) 
if !ok { 
    err = fmt.Errorf("get port extension failed, data type is :%v", reflect.TypeOf(data)) 
 return 
} 

来自 大脸猪 写于 2022-04-21 14:57 -- 更新于2022-04-21 15:11

0 人点赞