I have a relatively small app that reads from an AWS SQS queue. I have no control over these and the message structures and I need to handle at minimum two different message structures.
In an attempt to keep the codebase clean I opted to go down the route of using generic types for my queue handling functions as each strategy requires a different value passed to the handler function. I've slimmed this example down but it holds the pertanent data.
My question: Given that the generic type M could be one of two values how can I use that type when I know for sure I have one and only one of the contained types?
type MessageType interface {
types.Message | []types.Message
}
const (
CONCURRENT uint8 = 1 << iota
AGGREGATE
)
func SubscribeTo[M MessageType](queueName string, handler func(msg M, del chan *string), strategy uint8) {
go func() {
switch true {
case strategy&CONCURRENT != 0:
useConcurrentPoller(queueName, handler)
break
case strategy&AGGREGATE != 0:
default:
useAggregatePoller(queueName, handler)
break
}
}
}
func useConcurrentPoller[M MessageType](queueName string, concurrency int, handler func(msg M, del chan *string) {
// Queue connection and message retrieval logic removed for brevity
var deleteChannel = make(chan *string, 100)
for _, sqsMessage := range msgResult.Messages {
// sqsMessage is of type `types.Message` but errors as
// Cannot use 'sqsMessage' (type types.Message) as the type M
handler(sqsMessage, deleteChannel)
}
}
func useAggregatePoller[M MessageType](queueName string, handler func(msg M, del chan *string) {
// Queue connection and message retrieval logic removed for brevity
var deleteChannel = make(chan *string, 100)
handler(msgResult.Messages, deleteChannel)
}
I'm sure the solution is probably staring me in the face but somehow I can't see it. Type asserting on sqsMessage won't work as it's a non interface type (at least from what I gather).
Can anyone see how I can get this working?