go: 获取grpc extension 最近在接入交换机上报数据的时候,收到一个比较少见的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` ## 获取数据 ``` // 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 条评论