Stuff
This commit is contained in:
parent
8ad4e70623
commit
a4b74992c4
39
README.md
39
README.md
|
@ -31,14 +31,12 @@ import "github.com/localhots/gobelt/filecache"
|
|||
|
||||
```go
|
||||
ctx := context.Background()
|
||||
var val int
|
||||
filecache.Load(&val, "tmp/cache/items.json", func() interface{} {
|
||||
var items []Item
|
||||
var items []Item
|
||||
filecache.Load(&items, "tmp/cache/items.json", func() {
|
||||
err := conn.Query(ctx, "SELECT * FROM items").Load(&items).Error()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load items: %v", err)
|
||||
}
|
||||
return items
|
||||
})
|
||||
```
|
||||
|
||||
|
@ -83,6 +81,37 @@ s := setstring.New("one", "two")
|
|||
s.Add("three")
|
||||
s.Remove("one", "two").Add("four", "five")
|
||||
fmt.Println("Size:", s.Len()) // 3
|
||||
fmt.Println("Has one", s.Has("one"))
|
||||
fmt.Println("Has one", s.Has("one")) // false
|
||||
fmt.Println(s.SortedSlice()) // [three four five]
|
||||
```
|
||||
|
||||
### Config
|
||||
|
||||
```go
|
||||
import "github.com/localhots/gobelt/config"
|
||||
```
|
||||
|
||||
Describe configuration structure inside a target package.
|
||||
|
||||
```go
|
||||
package db
|
||||
|
||||
var conf struct {
|
||||
Flavor string `toml:"flavor"`
|
||||
DSN string `toml:"dsn"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
config.Require("db", &conf)
|
||||
}
|
||||
```
|
||||
|
||||
Load configuration from a `main` function:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
func main() {
|
||||
config.Load("config/config.toml")
|
||||
}
|
||||
```
|
|
@ -1 +1,34 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
var configs = map[string]interface{}{}
|
||||
|
||||
// Require registers a request for package configuration.
|
||||
func Require(key string, dest interface{}) {
|
||||
configs[key] = dest
|
||||
}
|
||||
|
||||
// Load reads the config file and distributes provided configuration to
|
||||
// requested destinations.
|
||||
func Load(path string) error {
|
||||
var conf map[string]toml.Primitive
|
||||
meta, err := toml.DecodeFile(path, &conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for key, prim := range conf {
|
||||
dest, ok := configs[key]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
err := meta.PrimitiveDecode(prim, dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
type numbers struct {
|
||||
Ary []int `toml:"ary"`
|
||||
I int `toml:"i"`
|
||||
}
|
||||
var nums numbers
|
||||
Require("numbers", &nums)
|
||||
numsExp := numbers{
|
||||
Ary: []int{1, 2, 3},
|
||||
I: 123,
|
||||
}
|
||||
|
||||
type words struct {
|
||||
Foo string `toml:"foo"`
|
||||
List struct {
|
||||
Foo []string `toml:"foo"`
|
||||
} `toml:"list"`
|
||||
}
|
||||
var w words
|
||||
Require("words", &w)
|
||||
wordsExp := words{
|
||||
Foo: "bar",
|
||||
List: struct {
|
||||
Foo []string `toml:"foo"`
|
||||
}{
|
||||
Foo: []string{"buzz", "fizz"},
|
||||
},
|
||||
}
|
||||
|
||||
err := Load("example.toml")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load config: %v", err)
|
||||
}
|
||||
if !cmp.Equal(numsExp, nums) {
|
||||
t.Errorf("Numbers mismatch: %s", cmp.Diff(numsExp, nums))
|
||||
}
|
||||
if !cmp.Equal(wordsExp, w) {
|
||||
t.Errorf("Words mismatch: %s", cmp.Diff(wordsExp, w))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
[numbers]
|
||||
ary = [1, 2, 3]
|
||||
i = 123
|
||||
|
||||
[words]
|
||||
foo = "bar"
|
||||
[words.list]
|
||||
foo = ["buzz", "fizz"]
|
|
@ -4,18 +4,15 @@ import (
|
|||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Load will look for a given file. If it exists, it would unmarshal its
|
||||
// contents into the given value. If the file does not exist, a supplied
|
||||
// function would be called and its output would be written to a file.
|
||||
func Load(val interface{}, filename string, fn func() interface{}) error {
|
||||
func Load(val interface{}, filename string, fn func()) error {
|
||||
_, err := os.Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
out := fn()
|
||||
reflect.ValueOf(val).Elem().Set(reflect.ValueOf(out))
|
||||
|
||||
fn()
|
||||
body, err := json.Marshal(val)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -12,9 +12,9 @@ func TestFileCache(t *testing.T) {
|
|||
var res int
|
||||
var nCalled int
|
||||
for i := 0; i < 10; i++ {
|
||||
err := Load(&res, filename, func() interface{} {
|
||||
err := Load(&res, filename, func() {
|
||||
nCalled++
|
||||
return exp
|
||||
res = exp
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error occurred while loading cache: %v", err)
|
||||
|
|
Loading…
Reference in New Issue