Search code examples
goencodegob

How to define a Send/Receive Function with interface{} using gob.Encoder()


I need to define a Send/Receive functions using gob package.

I defined Send() simply as follows:

func Send(enc *gob.Encoder, PKG interface{}) error {
    err := enc.Encode(PKG)
    return err
}

and Receive as follows:

func Receive(dec *gob.Decoder) (PKG interface{}) {

    err := dec.Decode(PKG)

    if err != nil {
        fmt.Println(PKG)
        Errors.Error(err, "Error receiving Package")
    }
    if PKG == nil {

        fmt.Println(PKG)
        Errors.Error(err, "Receiving empty Package")
    }
    return PKG
}

I am using these functions with various types: structs, concrete types, iota... I use to check the received type right after calling the Receive method.

However, unfortunately, I am not reaching the check breakpoints. These methods (Send/Receive) are wrongly defined. I am getting a <nil> pointer (panic: Receiving empty Package) on the receiver side although all sent items are exported.

currently, I am trying to send an int of the following defined type:

type ProcessType int

const (
    COORDINATOR ProcessType = iota
    SENDER
    NORMALPROCESS
)

I've read a lot of documentation, but were unable to understand the issue thoroughly. Can you please provide a neat and clean explanation.


Solution

  • Pass &PKG to encode and decode:

    func Send(enc *gob.Encoder, PKG interface{}) error {
        // Pass &PKG to force encoder to send PKG as a dynamic value.
        err := enc.Encode(&PKG)
        return err
    }
    
    func Receive(dec *gob.Decoder) (PKG interface{}) {
        // Pass address of result.
        err := dec.Decode(&PKG)
        if err != nil {
            fmt.Println(PKG)
            log.Fatal(err, "Error receiving Package")
        }
        if PKG == nil {
            fmt.Println(PKG)
            log.Fatal(err, "Receiving empty Package")
        }
        return PKG
    }
    

    The decode side should gob.Register values of all possible types passed to Send. Use this code for the iota example:

    gob.Register(COORDINATOR) // any value of type ProcessType works.
    

    Run the code on the Playground.