douzhangwei5265
douzhangwei5265
2018-04-23 13:55

通过名称设置protobuf属性

已采纳

To avoid too much spaghetti style code, I'd like to set certain properties of a golang protobuf object by name. So lets say there's some kind of .proto definition like

syntax = "proto3";
package foo;

message User {
    uint64 uid = 1;
    string name = 2;
}

and code accessing it like

o := foo.User{Name: "John Doe"}
o.Uid = 40

exists. I'd like to be able to set Uid without the dotted notation. Reflection constructs like

r := reflect.ValueOf(o)
f := reflect.Indirect(r).FieldByName("Uid")
f.SetUint(42)

seem to fail, because Uid is not addressable. I found several posts about struct fields not being addressable, but it's still unclear (to me as a "golang newbie") what has to be done in this context to make it work.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • duanjue9296 duanjue9296 3年前

    You need to pass a pointer to o to reflect.ValueOf. By simply passing the value, the fields of the struct will not be addressable.

    r := reflect.ValueOf(&o)
    f := reflect.Indirect(r).FieldByName("Uid")
    f.SetUint(42)
    

    If at all possible, however, I would try to implement this without reflection. Either use a map in your protocol buffer definition, or a switch in your Go code:

    switch name {
    case "Uid":
        o.Uid = uintValue
    case "Name"
        o.Name = stringValue
    }
    

    The non-reflect code is less likely to fail at runtime.

    点赞 评论 复制链接分享

为你推荐