Reputation: 9
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
Reputation: 55443
In
func (dat Data) Encode () io.Writer {
var ret io.Writer
enc := gob.NewEncoder(ret)
you
ret
of type io.Writer
nil
.nil
to gob.NewEncoder
which supposedly writes that value into its internal state.io.Writer
, it fails with that "invalid memory address or nil pointer dereference" error.Upvotes: 4
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