Skip to content

Instantly share code, notes, and snippets.

@PMaynard
Last active September 4, 2023 09:10
Show Gist options
  • Save PMaynard/a3ae177fb3d6f39d9c32a62253227f0f to your computer and use it in GitHub Desktop.
Save PMaynard/a3ae177fb3d6f39d9c32a62253227f0f to your computer and use it in GitHub Desktop.
Go serialise data to disk using encoding/gob.
/*
* Author: Peter Maynard (pete[at]port22[co/uk])
* Date: 2023 September 04
* Summary:
* Serialises a structure and writes to disk as a file.
* The data can be read back in and accessed as a normal
* struct.
*
* The data stored on disk is plain text so be careful
* where you store it
* Assocated blog post: https://not.just-paranoid.net/go-serialise-data-to-disk-using-encoding/gob/
First run with no existing file "./data.store"
freethink# go run disk-gob.go
2023/09/04 09:58:16 Could not find existing store.
2023/09/04 09:58:16 DS.Principles Initialised.
2023/09/04 09:58:16 Loaded 2 DS.Principles.
2023/09/04 09:58:16 Data Store Last Updated on: 0001-01-01 00:00:00 +0000 UTC
2023/09/04 09:58:16 example@email.com 65706574 77207361
2023/09/04 09:58:16 another@email.com 68207265 0a650a65
Second run with an existing file "./data.store"
freethink# go run disk-gob.go
2023/09/04 09:59:14 Loaded 2 DS.Principles.
2023/09/04 09:59:14 Data Store Last Updated on: 2023-09-04 09:58:16.034821023 +0100 BST
2023/09/04 09:59:14 example@email.com 65706574 77207361
2023/09/04 09:59:14 another@email.com 68207265 0a650a65
freethink# hexdump data.store -C
00000000 32 ff 81 03 01 01 05 53 74 6f 72 65 01 ff 82 00 |2......Store....|
00000010 01 02 01 09 55 70 64 61 74 65 64 4f 6e 01 ff 84 |....UpdatedOn...|
00000020 00 01 0a 50 72 69 6e 63 69 70 6c 65 73 01 ff 88 |...Principles...|
00000030 00 00 00 10 ff 83 05 01 01 04 54 69 6d 65 01 ff |..........Time..|
00000040 84 00 00 00 2a ff 87 04 01 01 19 6d 61 70 5b 73 |....*......map[s|
00000050 74 72 69 6e 67 5d 6d 61 69 6e 2e 50 72 69 6e 63 |tring]main.Princ|
00000060 69 70 6c 65 01 ff 88 00 01 0c 01 ff 86 00 00 33 |iple...........3|
00000070 ff 85 03 01 02 ff 86 00 01 03 01 05 45 6d 61 69 |............Emai|
00000080 6c 01 0c 00 01 0a 50 72 69 76 61 74 65 4b 65 79 |l.....PrivateKey|
00000090 01 0c 00 01 09 50 75 62 6c 69 63 4b 65 79 01 0c |.....PublicKey..|
000000a0 00 00 00 74 ff 82 01 0f 01 00 00 00 0e dc 87 92 |...t............|
000000b0 65 04 68 44 06 00 3c 01 02 06 74 65 73 74 30 31 |e.hD..<...test01|
000000c0 01 11 65 78 61 6d 70 6c 65 40 65 6d 61 69 6c 2e |..example@email.|
000000d0 63 6f 6d 01 08 36 35 37 30 36 35 37 34 01 08 37 |com..65706574..7|
000000e0 37 32 30 37 33 36 31 00 06 74 65 73 74 30 32 01 |7207361..test02.|
000000f0 11 61 6e 6f 74 68 65 72 40 65 6d 61 69 6c 2e 63 |.another@email.c|
00000100 6f 6d 01 08 36 38 32 30 37 32 36 35 01 08 30 61 |om..68207265..0a|
00000110 36 35 30 61 36 35 00 00 |650a65..|
00000118
*
*/
package main
import (
"bufio"
"encoding/gob"
"errors"
"log"
"os"
"time"
)
var DS *Store
type Store struct {
UpdatedOn time.Time
Principles map[string]Principle
}
type Principle struct {
Email string
PrivateKey string
PublicKey string
}
func main() {
filepath := "./data.store"
/* 1. Load or create new store. */
DS, err := read(filepath)
if err != nil {
log.Fatalf("Unable to load saved state: %v", err)
}
/* 2. Insert some data. */
if len(DS.Principles) == 0 {
DS.Principles = make(map[string]Principle)
log.Println("DS.Principles Initialised.")
DS.Principles["test01"] = Principle{Email: "example@email.com", PrivateKey: "65706574", PublicKey: "77207361"}
DS.Principles["test02"] = Principle{Email: "another@email.com", PrivateKey: "68207265", PublicKey: "0a650a65"}
}
log.Printf("Loaded %d DS.Principles.", len(DS.Principles))
log.Println("Data Store Last Updated on:", DS.UpdatedOn)
for _, principle := range DS.Principles {
log.Println(principle.Email, principle.PrivateKey, principle.PublicKey)
}
/* 3. Write to disk. */
err = write(filepath, &DS)
if err != nil {
log.Fatalf("Unable to write state: %v", err)
}
}
func read(path string) (Store, error) {
file, err := os.Open(path)
if err != nil {
log.Println("Could not find existing store.")
return Store{}, nil
}
fileReader := bufio.NewReader(file)
fileDecoder := gob.NewDecoder(fileReader)
res := Store{}
if err := fileDecoder.Decode(&res); err != nil {
return Store{}, errors.New("Unable to decode")
}
file.Close()
return res, nil
}
func write(path string, data *Store) error {
data.UpdatedOn = time.Now()
file, err := os.Create(path)
if err != nil {
return errors.New("Unable to write file")
}
defer file.Close()
fileWriter := bufio.NewWriter(file)
fileEncoder := gob.NewEncoder(fileWriter)
if err := fileEncoder.Encode(data); err != nil {
return errors.New("Unable to encode")
}
fileWriter.Flush()
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment