56 lines
955 B
Go
56 lines
955 B
Go
package utility
|
|
|
|
import (
|
|
"errors"
|
|
"reflect"
|
|
"sync"
|
|
)
|
|
|
|
type Lazy interface {
|
|
Value(value interface{}) (err error)
|
|
}
|
|
|
|
var (
|
|
TypeMismatched = errors.New("type mismatched")
|
|
)
|
|
|
|
type lazy struct {
|
|
lock *sync.Once
|
|
fetch func() (value interface{}, err error)
|
|
value interface{}
|
|
done bool
|
|
}
|
|
|
|
func (l *lazy) Value(value interface{}) (err error) {
|
|
if l.done {
|
|
l.setValueTo(value)
|
|
return
|
|
}
|
|
l.lock.Do(func() {
|
|
if l.value, err = l.fetch(); err != nil {
|
|
l.lock = new(sync.Once)
|
|
return
|
|
} else {
|
|
l.setValueTo(value)
|
|
l.done = true
|
|
}
|
|
})
|
|
return
|
|
}
|
|
|
|
func (l lazy) setValueTo(receiver interface{}) (err error) {
|
|
rv := reflect.Indirect(reflect.ValueOf(receiver))
|
|
vv := reflect.ValueOf(l.value)
|
|
if vv.Type().AssignableTo(rv.Type()) && rv.CanSet() {
|
|
rv.Set(reflect.ValueOf(l.value))
|
|
}
|
|
return TypeMismatched
|
|
}
|
|
|
|
func NewLazy(fetch func() (value interface{}, err error)) Lazy {
|
|
return &lazy{
|
|
lock: new(sync.Once),
|
|
fetch: fetch,
|
|
}
|
|
}
|