I have generated protobuf and want to make a concreate of message.
something like this:
type NatsSubscriber[T proto.Message] struct {
NatsClient *nats.Conn
Log logger.Log
OnReceiveEvent func(event T) (response string)
}
func (n *NatsSubscriber[T]) RegisterHandlers() {
for _, routeName := range n.Topics {
_, err := n.NatsClient.Subscribe(routeName, func(req *nats.Msg) {
uuids := req.Header[`UUID`]
var uuid string
if len(uuids) > 0 {
uuid = uuids[0]
}
var event T // how to make this concrete?
n.Log.Infof("natsClient[%T] %s receive %s", event, routeName, uuid)
err := proto.Unmarshal(req.Data, event)
if err != nil {
n.Log.Errorf("natsClient[%T].Subscribe.Unmarshal: %s %s %v", event, uuid, routeName, err)
err = req.Nak()
if err != nil {
n.Log.Errorf("natsClient[%T].Subscribe.Nak: %s %s %v", event, uuid, routeName, err)
}
return
}
resp := n.OnReceiveEvent(event)
if err := req.Respond([]byte(resp)); err != nil {
n.Log.Errorf("natsClient[%T].Subscribe.Respond: %s %s %v", event, uuid, routeName, err)
}
})
if err != nil {
var event T
n.Log.Errorf("natsClient[%T].Subscribe: %s %v", event, routeName, err)
}
}
}
and called by something like this:
blaSubscriber := NatsSubscriber[*apiProto.BlaReq]{
NatsClient: natsClient,
Topics: topics1,
Log: log,
OnReceiveEvent: func(event *apiProto.BlaReq) (resp string) {
...
},
}
fooSubscriber := NatsSubscriber[*apiProto.FooReq]{
NatsClient: natsClient,
Topics: topics2,
Log: log,
OnReceiveEvent: func(event *apiProto.FooReq) (resp string) {
...
},
}
...
If without protobuf, I can just use normal struct and it would deserialized normally.
fooSub := natsSubscriber[FooReq]{ ... }
// then on RegisterHandlers
var event T
msgpack.Unmarshal(req.Data, event) // no error because concreate
The problem is that apiProto.BlaReq
have to be a pointer so it can satisfy the proto.Message
interface on the generic, but that line will have error because I don’t know how to make it a concrete from pointer
var event T // how to make this concrete?
err := proto.Unmarshal(req.Data, event) // pointer to nil
So how to make a concrete of pointer, or how to declare the generic as concrete but still satisfy the proto.Message
interface?