英文:
Get a FieldDescriptor without hard-coding the field name (proto message)
问题
给定以下的 proto message:
message MyMsg {
string my_field = 1;
string your_field=2;
}
...可以使用 protoreflect 包来获取每个字段的描述符:
protoMessage := myMsg.ProtoReflect()
messageDescriptor := protoMessage.Descriptor() // protobuf 类型信息
fieldDescriptors := messageDescriptor.Fields() // 字段声明列表
获取特定字段的 field descriptor 很简单:
fieldDescriptor := fieldDescriptors.ByTextName("my_field") // 描述一个字段
是否可以在不硬编码字段名 "my_field"
的情况下实现这一点?我猜如果能使用生成的代码来引用我感兴趣的字段会很好。类似于(不是有效的代码):
fieldDescriptor := fieldDescriptors.ByTextName(pb.MyMsg.MyField) // 描述一个字段
这样,如果字段名发生变化,它将在编译时被捕获,甚至可以通过 IDE 的静态分析来捕获。
FieldDescriptors 类型有三个通过名称获取字段描述符的方法:
ByName(s Name)
ByJSONName(s string)
ByTextName(s string)
ByJSONName
和 ByTextName
都需要硬编码的字段名(作为字符串),而 ByName
接受一个 Name,它被类型化为字符串。总之,我在 protoreflect 包中没有找到指向解决方案的任何内容。
背景
Field masks 是支持部分资源更新的推荐方法。在字段掩码中提供的掩码上进行迭代非常简单:
protoMessage := myMsg.ProtoReflect()
messageDescriptor := protoMessage.Descriptor() // protobuf 类型信息
fieldDescriptors := messageDescriptor.Fields() // 字段声明列表
// 在字段掩码中迭代字段路径
for _, p := range mask.GetPaths() {
// 找到字段路径的字段描述符
fieldDescriptor := fieldDescriptors.ByTextName(p)
if fieldDescriptor == nil {
// 找不到字段路径的字段描述符
return
}
// 太好了,字段路径指向一个字段,让我们使用它
switch p {
case "my_field":
// 客户端想要更新 MyMsg.my_field
case "your_field":
// 客户端想要更新 MyMsg.your_field
}
}
问题是,为了实际更新 MyMsg
中的正确字段,有必要在 switch
语句中硬编码字段名。
英文:
Given the following proto message
message MyMsg {
string my_field = 1;
string your_field=2;
}
...the protoreflect package can be used to get a descriptor for each field
protoMessage := myMsg.ProtoReflect()
messageDescriptor := protoMessage.Descriptor() // protobuf type information
fieldDescriptors := messageDescriptor.Fields() // list of field declarations
Getting a field descriptor for a specific field is trivial
fieldDescriptor := fieldDescriptors.ByTextName("my_field") // describes a field
Can this be achieved without hard-coding the field name "my_field"
? I guess it would be nice to use the generated code to refer to the field I'm interested in. Something like (not working code)
fieldDescriptor := fieldDescriptors.ByTextName(pb.MyMsg.MyField) // describes a field
This way, if the field name changes, it will be caught at compile time, or even from static analysis by an IDE.
The FieldDescriptors type has three methods for getting a field descriptor by name:
ByName(s Name)
ByJSONName(s string)
ByTextName(s string)
ByJSONName
and ByTextName
both require hard-coded field names (as strings), and by ByName
accepts a Name which is type'd to a string. The upshot is, I don't see anything in the protoreflect package that points to a solution.
Context
Field masks are the recommended way to support partial resource updates. It's trivial to iterate over the masks provided in a field mask
protoMessage := myMsg.ProtoReflect()
messageDescriptor := protoMessage.Descriptor() // protobuf type information
fieldDescriptors := messageDescriptor.Fields() // list of field declarations
// iterate over the field paths in the field mask
for _, p := range mask.GetPaths() {
// find the field descriptor for the field path
fieldDescriptor := fieldDescriptors.ByTextName(p)
if fieldDescriptor == nil {
// field descriptor cannot be found for the field path
return
}
// great, the field path points to a field, let's use it
switch p {
case "my_field":
// the client wants to update MyMsg.my_field
case "your_field":
// the client wants to update MyMsg.your_field
}
}
The problem is, in order to actually update the correct field in MyMsg
, it's necessary to hard-code the field name in the switch
statement.
答案1
得分: 1
接口也有ByNumber
方法。
我假设(我没有使用过这个方法),你可以从你的示例中给出1
。
当然还有Get
方法,这样你就可以枚举所有的FieldDescriptors。
我认为想要反射生成的(结构体)类型并在它们之间进行枚举是合理的,但感觉像是无穷递归。
如果你能提出你无法在没有所需方法的情况下解决的问题,可能会有其他答案帮到你。
英文:
The interface has ByNumber
too
I assume (I've not used the method) that you could give this 1
from your example.
And Get
, of course so that you can enumerate all of the FieldDescriptors.
I think it's not unreasonable to want to reflect (!) the generated (struct) types and enumerate across them but it feels like turtles-all-the-way-down.
It may help solicit other answers if you could present the problem that you're unable to solve without the desired method?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论