Help regarding Protoreflect

I have a gRPC service which takes Request and Response with specific formats.

message Response {
     string ID = 1;
     ScorerA ScrA = 2;
     ScorerB ScrB = 3;
}
// Any one of ScorerA and ScorerB needs to populated in Response and will be decided at runtime

message ScorerA {
    string Name = 1;
}

message ScorerB {
    string Section = 1;
}

I have created map of Scorer Name to Scorer Type:

var scrA *pb.ScorerA = &pb.ScorerA{}
var scrAType protoreflect.MessageType = scrA.ProtoReflect().Type()

var scrB *pb.ScorerB = &pb.ScorerB{}
var scrBType protoreflect.MessageType = scrB.ProtoReflect().Type()

ScorerTypes := map[string]protoreflect.MessageType {
     "ScorerA":  scrAType
     "ScorerB":  scrBType
}

In my gRPC server I am getting the Scorer Name at runtime based on some condition.

scorerName := "ScorerA" // Let's say

Now I create an empty structure (not to be confused with go struct) of type scrAType and set values for fields:

var recType protoreflect.MessageType = ScorerTypes[scorerName]
var rec protoreflect.Message = recType.New()
.
.
.
rec.Set(_, _) // Setting values for fields

Finally converted to protoreflect.ProtoMessage using:

var finalScorer protoreflect.ProtoMessage = rec.Interface()

Reference: https://pkg.go.dev/google.golang.org/protobuf/reflect/protoreflect#hdr-Go_Type_Descriptors

Now my gRPC server has return type of *pb.Response, So:

resp := &pb.Response{ID: "1", ScrA: finalScorer}

This gives the following error:

cannot use finalScorer (variable of type protoreflect.ProtoMessage) as *"proto".ScorerA value in struct literal

How can I convert protoreflect.ProtoMessage to actual pb (lets say pb.ScorerA)?
If there’s any better way to handle this usecase please let me know.

could the problem be that you are initializing nested struct.

without compiling, could this work:

resp := &pb.Response{ID: "1", ScrA:ScorerA{finalScorer}}

if not, try to set the resp fields outside of initialization.

rsp := &pb.Response{ID: "1"}

rspMsg := rsp.ProtoReflect()
rspType := rspMsg.Type()
rspFields := rspType.Descriptor().Fields()

rv := protoreflect.ValueOf(rsp.ProtoReflect())
rv.Message().Set(rspFields.ByTextName("ScrA"), protoreflect.ValueOf(finalScorer.ProtoReflect()))
1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.