4

I want to know how to set an Enum value dynamically.

I have the following .proto file:

syntax = "proto3";
package garden;

option go_package = "proto/garden";

message Garden {
  enum Flower {
    Rose = 0;
    Acacia = 1;
    Firethorn = 2;
    Nemophila = 3;
  }
  Flower flower = 1;
}

One way to set the enum is the following:

garden := pb.Garden{}
garden.Flower = pb.Garden_Rose

I want to generate my garden dynamically and only have the value "Rose". There is the value mapping but the following does not work:

garden := pb.Garden{}
garden.Flower = pb.Garden_Flower_value["Rose"] // gives error: cannot use garden.Garden_Flower_value[flower] (type int32) as type garden.Garden_Flower in assignment

garden.Flower = 0 // works somehow??

I assume that I can use the protoreflect package to set the value. Unfortunately, it is not clear to me yet how it works.

garden.Flower = protoreflect.EnumNumber(pb.Garden_Rose)

Furthermore, I want to set ".Flower" dynamically. I figured out how to set fields in a struct dynamically but lack the knowledge how to cast a protoreflect.Value to a reflect.Value type.

Konrad
  • 107
  • 8

2 Answers2

1

If someone wants to know how to do all of this dynamically. I finally figured it out:

func main() {
    var garden = pb.Garden{}
    var gardenProto = garden.ProtoReflect()
    var fields = gardenProto.Descriptor().Fields()
    var flower = fields.ByName(protoreflect.Name("flower"))
    var rose = protoreflect.Name("Rose")
    var enumValue = protoreflect.ValueOfEnum(protoreflect.EnumNumber(flower.Enum().Values().ByName(rose).Number()))
    gardenProto.Set(flower, enumValue)
    fmt.Print(garden.GetFlower())
}

When changing the string "Rose" to any of the other valid Flowers the enum is automatically updated. Furthermore, make sure that the field name is the one as specified in the .proto file. In this example it was flower.

Konrad
  • 107
  • 8
0

Have you already tried this approach?

flower := "Rose"
garden := pb.Garden{}
garden.Flower = pb.Garden_Flower(pb.Garden_Flower_value[flower])
fmt.Println(garden.Flower.String()) // Rose
Matteo
  • 37,680
  • 11
  • 100
  • 115
  • 1
    your example does not compile for me: ``` cannot use garden.Garden_Flower_value[flower] (type int32) as type garden.Garden_Flower in assignment ``` – Konrad Oct 21 '20 at 11:30
  • Hi @Konrad you are right, I've updated my answer with the correct type cast. Should be fine now (I'm not sure about the generated enum struct name) – Matteo Oct 21 '20 at 12:08