Note that your code is not type-safe. It panics when instantiated with a
type that does not use a pointer receiver: https://go.dev/play/p/eHUKtXvgwAu
ISTM that being more type-safe would be an advantage here.

On Sat, Dec 30, 2023 at 8:47 PM Mazen Harake <mazen.har...@gmail.com> wrote:

> @Alex,
>
> Oh, and I should point out that I actually went with what you mentioned in
> your 1st point, I was just curious if it was possible to do it the other
> way.
>
> On Saturday 30 December 2023 at 20:36:07 UTC+1 Mazen Harake wrote:
>
>> Cheers @Axel for the input. I think I worked it out though.
>>
>> The bad thing is that it involves reflection but considering that it
>> greatly simplifies the code base I would argue that it is good enough for
>> now.
>>
>> First, regarding your 2nd point of passing buf as a parameter to Decode()
>> instead of through a field. The examples I gave are made up to resemble the
>> actual situation to simplify it but what actually happens is that each
>> message has a "BaseMessage" struct. When receiving some payload the common
>> parts of the message (such as the length, type and checksums) are always
>> decoded into base message, then depending on the type the specific message
>> type is created and the rest of the bytes are decoded according to what
>> that message expects.
>>
>> Anyway... this is the solution I came up with (for internet searching
>> completeness sake):
>>
>> func DecodeMessage[T Decoder](bm *BaseMessage) (T, bool) {
>>   var mT T
>>   m := reflect.New(reflect.TypeOf(mT).Elem()).Interface().(T)
>>   d := Decoder(m)
>>   ok := d.Decode( bm )
>>   return d.(T), ok
>> }
>>
>> This function is then called with the following code example:
>>
>> transactionMsg, ok :=  DecodeMessage [*TransactionMessage](baseMsg)
>>
>> Cheers
>>
>>
>> On Friday 29 December 2023 at 23:17:47 UTC+1 Axel Wagner wrote:
>>
>> 1. Note that you can just write `NewMessage(&MessageA{}, buf)` in your
>> example, as the type can be inferred.
>> 2. You can use a constraint on a pointer-receiver to somewhat simplify
>> that: https://go.dev/play/p/pEu02Bn9t3f
>> That is not *quite* what you are asking for. It is not actually possible
>> to really do what you want, because there is no way to express a constraint
>> that "the type needs to have a `Buf []byte` field, which would be needed to
>> make your `m := &MessageAStruct{Buf: b}` work. But there isn't really a
>> reason to pass the buffer as a field anyways, in my opinion - passing it as
>> a parameter to `Decode` seems far more logical.
>>
>> On Fri, Dec 29, 2023 at 8:52 PM Mazen Harake <mazen....@gmail.com> wrote:
>>
>> Hi all,
>>
>> Assume I have a tcp server with incoming tcp packets which can be decoded
>> in differently depending on some headers in that packet.
>>
>> Each message that comes in has a struct associated with it which can be
>> created with the traditionale NewX..(buf []byte ...). After creating the
>> object (or inside the constructor, doesn't matter) the Decode() function is
>> called to interpret the bytes and assign all the fields of the struct.
>>
>> This works fine. But is it possible to eliminate all the 200+ functions
>> that do the same thing but use a generic function instead?
>>
>> So instead of this:
>>
>> func NewMessageA(buf []byte) *MessageAStruct {
>>   m := &MessageAStruct{
>>     Buf: buf,
>>   }
>>   m.Decode()
>>   return m
>> }
>>
>> msg := NewMessageA(buf)
>>
>> I would rather do something like this:
>>
>> msg := NewMessage[A](buf)
>>
>> and I would've wanted to do something like this in the generic function
>>
>> func NewMessage[T](buf []byte) *T {
>>   // ... something?
>>   // call Decode()
>>   // return *T
>> }
>>
>> I can do it by creating an interface called Decodable and then passing
>> the the type and the "empty" object to the generic function but it feels
>> clumsy and weird somehow and I probably wouldn't gain very much. E.g.
>>
>> func NewMessage[T Decodable](t T, buf []byte) T {
>>   t.Decode(buf)
>>   return t
>> }
>>
>> and I would call it like this
>>
>> msg := NewMessage[*MessageA](&MessageA{}, buf)
>>
>> The most likely answer is "You shouldn't do it like that", which would be
>> a completely fine and acceptable answer, but *can* you achieve this?
>>
>> Cheers
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to golang-nuts...@googlegroups.com.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/golang-nuts/5dc5715c-aad9-431f-8ea0-9c89db46d873n%40googlegroups.com
>> <https://groups.google.com/d/msgid/golang-nuts/5dc5715c-aad9-431f-8ea0-9c89db46d873n%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/8149b0ed-0846-4634-8503-899a05ea8a25n%40googlegroups.com
> <https://groups.google.com/d/msgid/golang-nuts/8149b0ed-0846-4634-8503-899a05ea8a25n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfFi6cF48ayVYyg6mcREisP5SB6fd87A%2Bsy-XMA6B0fZEw%40mail.gmail.com.

Reply via email to