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