1

I try to create marshal func for struct Item.

So the question is, why the first example gives stackoverflow for goroutine and second works correctly?

  1. Call method with receiver
type Item struct{
  a int
}

func some(items []Item){
   for _,i:=range items{
      buf,err:=i.MarhsalBinary()
      fmt.Println(buf.Bytes(), err)
}

func (i Item) MarshalBinary() ([]byte, error) {
   var (
       buf bytes.Buffer
       err error
   )
   if err = gob.NewEncoder(&buf).Encode(i); err != nil { // endless loop here
       return nil, err
   }

   return buf.Bytes(), err
}
  1. This is pass by value.
type Item struct{
  a int
}

func some(items []Item){
   for _,i:=range items{
      buf,err:=MarhsalBinary(i)
      fmt.Println(buf.Bytes(), err)
}

func MarshalBinary(i Item) ([]byte, error) {
   var (
       buf bytes.Buffer
       err error
   )
   if err = gob.NewEncoder(&buf).Encode(i); err != nil { // works correctly
       return nil, err
   }

   return buf.Bytes(), err
}
NIck
  • 163
  • 1
  • 2
  • 12
  • 4
    https://golang.org/pkg/encoding/gob/#pkg-overview *"Gob can encode a value of any type implementing the GobEncoder or [`encoding.BinaryMarshaler`](https://golang.org/pkg/encoding/#BinaryMarshaler) interfaces **by calling the corresponding method**, in that order of preference."* -- That means that `Encode(i)` calls `i.MarshalBinary` which calls `Encode(i)` which calls `i.MarshalBinary` which calls `Encode(i)` which calls `i.MarshalBinary` ... ad infinitum. – mkopriva Feb 21 '21 at 09:00
  • Ah, got it. So I just need to change the name of my func in order to make it work correctly. – NIck Feb 24 '21 at 08:05
  • Method, yes. For example change `func (i Item) MarshalBinary() ([]byte, error) {` to `func (i Item) MarshalToBinary() ([]byte, error) {` and you should be good to go. – mkopriva Feb 24 '21 at 08:07

0 Answers0