为避免过多的意大利面风格代码,我想按名称设置 golang protobuf对象的某些属性。因此,我们可以说某些.proto
定义如
syntax = "proto3";
package foo;
message User {
uint64 uid = 1;
string name = 2;
}
和代码访问它
o := foo.User{Name: "John Doe"}
o.Uid = 40
存在。我希望能够在没有点缀符号的情况下设置Uid
。反思构造如
r := reflect.ValueOf(o)
f := reflect.Indirect(r).FieldByName("Uid")
f.SetUint(42)
似乎失败了,因为Uid
不是可寻址的。我发现了一些关于结构字段不可寻址的帖子,但它仍然不清楚(对我来说是一个" golang newbie")在这种情况下必须做什么让它发挥作用。
答案 0 :(得分:1)
您需要将指针o
传递给reflect.ValueOf
。通过简单地传递值,结构的字段将不可寻址。
r := reflect.ValueOf(&o)
f := reflect.Indirect(r).FieldByName("Uid")
f.SetUint(42)
但是,如果可能的话,我会尝试在没有反思的情况下实现这一点。在协议缓冲区定义中使用映射,或在Go代码中使用开关:
switch name {
case "Uid":
o.Uid = uintValue
case "Name"
o.Name = stringValue
}
非反射代码在运行时不太可能失败。