Last active
January 27, 2025 21:23
-
-
Save peterhellberg/c531189dff8a126540d587f2c4501422 to your computer and use it in GitHub Desktop.
Minimal parametric JSON file store in Go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"io" | |
"os" | |
"path/filepath" | |
"sync" | |
) | |
type ( | |
Name string | |
Habitat []string | |
) | |
type Fish struct { | |
ID string | |
Scientific Name | |
English Name | |
Swedish Name | |
Habitat Habitat | |
} | |
func main() { | |
if err := run("fishes", os.Stdout); err != nil { | |
panic(err) | |
} | |
} | |
func run(dir string, out io.Writer) error { | |
cacheDir, err := os.UserCacheDir() | |
if err != nil { | |
return err | |
} | |
path := filepath.Join(cacheDir, dir) | |
fishes, err := Store[Fish](path) | |
if err != nil { | |
return err | |
} | |
// Data grabbed from https://raw.githubusercontent.com/You-now-Who/dataset/refs/heads/main/List%20of%20fishes%20found%20in%20Sweden/List%20of%20fishes%20found%20in%20Sweden.csv | |
fishes.Set("abborre", Fish{ | |
ID: "abborre", | |
Scientific: "Perca fluviatilis", | |
English: "European perch", | |
Swedish: "Abborre", | |
Habitat: Habitat{ | |
"fresh", | |
"brackish", | |
}, | |
}) | |
fishes.Set("gädda", Fish{ | |
ID: "gädda", | |
Scientific: "Esox lucius", | |
English: "Pike", | |
Swedish: "Gädda", | |
Habitat: Habitat{ | |
"fresh", | |
"brackish", | |
}, | |
}) | |
fishes.Set("makrill", Fish{ | |
ID: "makrill", | |
Scientific: "Scomber scombrus", | |
English: "Atlantic mackerel", | |
Swedish: "Makrill", | |
Habitat: Habitat{ | |
"marine", | |
}, | |
}) | |
a, err := fishes.Get("abborre") | |
if err != nil { | |
return err | |
} | |
g, err := fishes.Get("gädda") | |
if err != nil { | |
return err | |
} | |
m, err := fishes.Get("makrill") | |
if err != nil { | |
return err | |
} | |
return encodeJSON(out, []Fish{a, g, m}) | |
} | |
type Disk[T any] struct { | |
mu sync.RWMutex | |
path string | |
} | |
func Store[T any](path string) (*Disk[T], error) { | |
perm := os.ModeDir | os.ModePerm | |
if err := os.MkdirAll(path, perm); err != nil { | |
return nil, err | |
} | |
return &Disk[T]{path: path}, nil | |
} | |
func (d *Disk[T]) Set(id string, v T) error { | |
d.mu.Lock() | |
defer d.mu.Unlock() | |
f, err := os.Create(d.name(id)) | |
if err != nil { | |
return err | |
} | |
defer f.Close() | |
return encodeJSON(f, v) | |
} | |
func (d *Disk[T]) Get(id string) (v T, err error) { | |
d.mu.RLock() | |
defer d.mu.RUnlock() | |
f, err := os.Open(d.name(id)) | |
if err != nil { | |
return v, err | |
} | |
defer f.Close() | |
return v, json.NewDecoder(f).Decode(&v) | |
} | |
func (d *Disk[T]) name(id string) string { | |
return filepath.Join(d.path, id+".json") | |
} | |
func encodeJSON(w io.Writer, v any) error { | |
enc := json.NewEncoder(w) | |
enc.SetIndent("", " ") | |
return enc.Encode(v) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I asked
deepseek-r1:14b
to describe what the latest version does: