ENic2004
ENic2004

Reputation: 9

gob encoding is crashing

I wanted to develop a type data struct for the implementation of storage on disk. I ran into a problem while encoding the data object to bytes. For the encoding I wanted to use the encoding/gob package.

package data

import (
    "encoding/gob"
    "io"
)
func NewKey(key string) Data {
    ret := Data{MsgType: "key", Value: key}
    return ret
}

func NewData(d string) Data {
    ret := Data{MsgType: "data", Value: d}
    return ret
}

type Data struct {
    MsgType string
    Value   string
}

func (dat Data) Encode () io.Writer {
    var ret io.Writer
    enc := gob.NewEncoder(ret)
    _ = enc.Encode(dat)
    // if err != nil {
    //  panic(err)
    // }
    return ret
}

This is the code of the data package. My goal is to convert the Data type to a byte slice, so that I can store it with diskv. My main code looks like this: package main

import (
    "fmt"
    "pkg"
)

func main() {
    testData := data.Data{MsgType:"string", Value:"1"}
    ret := testData.Encode()
    // fmt.Println(ret)
    fmt.Sprintf("%T", ret)
}

But when I run the code with go run I get the following output:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x18 pc=0x4a15b4]

goroutine 1 [running]:
encoding/gob.(*Encoder).writeMessage(0xc0000440a0, 0x0, 0x0, 0xc0000440d8)
    C:/Program Files/Go/src/encoding/gob/encoder.go:82 +0x134
encoding/gob.(*Encoder).sendActualType(0xc0000440a0, 0x0, 0x0, 0xc000037600, 0xc0000375c0, 0x506800, 0x4d2580, 0x38)
    C:/Program Files/Go/src/encoding/gob/encoder.go:107 +0x223
encoding/gob.(*Encoder).sendType(0xc0000440a0, 0x0, 0x0, 0xc000037600, 0x506800, 0x4d2580, 0xc000067de0)
    C:/Program Files/Go/src/encoding/gob/encoder.go:169 +0xda
encoding/gob.(*Encoder).sendTypeDescriptor(0xc0000440a0, 0x0, 0x0, 0xc000037600, 0xc0000375c0)
    C:/Program Files/Go/src/encoding/gob/encoder.go:191 +0xd9
encoding/gob.(*Encoder).EncodeValue(0xc0000440a0, 0x4d2580, 0xc000004c00, 0x99, 0x0, 0x0)
    C:/Program Files/Go/src/encoding/gob/encoder.go:244 +0x2f3
encoding/gob.(*Encoder).Encode(0xc0000440a0, 0x4d2580, 0xc000004c00, 0xc000004c00, 0x0)
    C:/Program Files/Go/src/encoding/gob/encoder.go:176 +0xad
pkg.Data.Encode(0x4e66e9, 0x6, 0x4e614a, 0x1, 0x0, 0x0)
    C:/Users/eliap/OneDrive/Dokumente/Programming/Go/src/pkg/data.go:25 +0xa2
main.main()
    C:/Users/eliap/OneDrive/Dokumente/Programming/Go/src/test.go:10 +0x56
exit status 2
[Finished in 1.1s with exit code 1]
[cmd: ['go', 'run', 'C:\\Users\\eliap\\OneDrive\\Dokumente\\Programming\\Go\\src\\test.go']]
[dir: C:\Users\eliap\OneDrive\Dokumente\Programming\Go\src]
[path: C:\ProgramData\DockerDesktop\version-bin;C:\Program Files\Docker\Docker\Resources\bin;C:\Program Files\Python37\;C:\Windows\System32;C:\Program Files\Typora\bin;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Python37\Scripts;C:\MinGW\bin;C:\Program Files\Go\bin;C:\Program Files\Git\cmd;C:\Program Files\micro-1.4.1;C:\Program Files\Microsoft VS Code\bin;C:\Program Files (x86)\Midnight Commander;C:\Ruby26-x64\bin;C:\Users\eliap\AppData\Local\Microsoft\WindowsApps;C:\Users\eliap\go\bin]

I'm using go version go1.12 windows/amd64, Windows 10 and Sublime Text 3 (If it matters) If you have a better solution/implementation for the Encode method it would be even nicer.

Upvotes: 0

Views: 349

Answers (2)

kostix
kostix

Reputation: 55443

In

func (dat Data) Encode () io.Writer {
    var ret io.Writer
    enc := gob.NewEncoder(ret)

you

  1. Declare a variable ret of type io.Writer
  2. Do not initialize it, so it has the zero-value for its type, nil.
  3. You pass that nil to gob.NewEncoder which supposedly writes that value into its internal state.
  4. As soon as you try to encode something using that encoder, and it decides it's time to actually write something to the provided io.Writer, it fails with that "invalid memory address or nil pointer dereference" error.

Upvotes: 4

Jonathan Hall
Jonathan Hall

Reputation: 79516

The problem is that you're trying to write to a nil io.Writer:

var ret io.Writer
enc := gob.NewEncoder(ret)

ret is nil. So it's going to panic (as it does) when trying to write to it.

The normal way to write an Encode() method, would be to take an io.Writer as an argument:

func (dat Data) Encode(w io.Writer) error {
    enc := gob.NewEncoder(ret)
    return enc.Encode(dat)
}

Then you would call this method with an existing io.Writer (which may be a file, or a network socket, or whatever):

file, err := os.Create("somefile")
...
if err := dat.Encode(file); err != nil {
    fmt.Printf("Failed to encode: %s\n", err)
}

Upvotes: 3

Related Questions