Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><a href="http://play.golang.org/p/THNb3C-TLq" rel="nofollow">http://play.golang.org/p/THNb3C-TLq</a></p> <pre><code>package main import ( "fmt" ) type ChangeHandler func(interface{}) type EventedChanger interface { Get(name string) interface{} Set(name string, value interface{}) EventedChanger OnChange(name string, listener ChangeHandler) EventedChanger } type MyChanger struct { data map[string]interface{} listeners map[string][]ChangeHandler } func (m *MyChanger) Get(name string) interface{} { val, ok := m.data[name] if !ok { return nil } return val } func (m *MyChanger) Set(name string, value interface{}) EventedChanger { m.data[name] = value if listeners, ok := m.listeners[name]; ok { for _, l := range listeners { l(value) } } return m } func (m *MyChanger) OnChange(name string, listener ChangeHandler) EventedChanger { m.listeners[name] = append(m.listeners[name], listener) return m } func NewMyChanger() *MyChanger { return &amp;MyChanger{ make(map[string]interface{}), make(map[string][]ChangeHandler), } } func main() { c := NewMyChanger() h := func(value interface{}) { c.Set("fullname", fmt.Sprint(c.Get("firstname"), c.Get("lastname"))) } q := func(value interface{}) { fmt.Println("Full name:", value) } c.OnChange("firstname", h).OnChange("lastname", h).OnChange("fullname", q) c.Set("firstname", "Walter").Set("lastname", "Smith") } </code></pre> <p>Output is:</p> <pre><code>Full name: Walter &lt;nil&gt; Full name: Walter Smith Program exited. </code></pre> <p>You could improve it by making it concurrent and/or execute handlers in parallel for instance.</p> <p><strong>EDIT:</strong></p> <p><a href="http://play.golang.org/p/msgaBXQwt_" rel="nofollow">http://play.golang.org/p/msgaBXQwt_</a></p> <p>I have made a more <em>generic</em> version of this to comply with your requirements of being lazy and cached:</p> <pre><code>package main import ( "fmt" ) type Getter func(string) interface{} type Setter func(string, interface{}) type GetSetter interface { Get(string) interface{} Set(string, interface{}) GetSetter RegisterGetter(string, Getter) GetSetter RegisterSetter(string, Setter) GetSetter } type LazyGetSetter struct { data map[string]interface{} getters map[string]Getter setters map[string]Setter } func NewLazyGetSetter() *LazyGetSetter { return &amp;LazyGetSetter{ make(map[string]interface{}), make(map[string]Getter), make(map[string]Setter), } } func (l *LazyGetSetter) Get(name string) interface{} { if getter, ok := l.getters[name]; ok { return getter(name) } if val, ok := l.data[name]; ok { return val } return nil } func (l *LazyGetSetter) Set(name string, value interface{}) *LazyGetSetter { if setter, ok := l.setters[name]; ok { setter(name, value) } else { l.data[name] = value } return l } func (l *LazyGetSetter) RegisterGetter(name string, getter Getter) *LazyGetSetter { l.getters[name] = getter return l } func (l *LazyGetSetter) RegisterSetter(name string, setter Setter) *LazyGetSetter { l.setters[name] = setter return l } type CachedLazyGetSetter struct { *LazyGetSetter cache map[string]interface{} } func NewCachedLazyGetSetter() *CachedLazyGetSetter { return &amp;CachedLazyGetSetter{ NewLazyGetSetter(), make(map[string]interface{}), } } func (c *CachedLazyGetSetter) Cache(name string, value interface{}) *CachedLazyGetSetter { c.cache[name] = value return c } func (c *CachedLazyGetSetter) FetchCache(name string) interface{} { if val, ok := c.cache[name]; ok { return val } return nil } func main() { l := NewCachedLazyGetSetter() l.RegisterGetter("fullname", func(name string) interface{} { if cached := l.FetchCache(name); cached != nil { return cached } f := fmt.Sprintf("%s %s", l.Get("firstname"), l.Get("lastname")) l.Cache(name, f) return f }) l.Set("firstname", "Walter").Set("lastname", "Smith") fmt.Println(l.Get("fullname")) } </code></pre> <p>As to your comment: a map lookup will outperform reflection by orders of magnitude.</p> <p>Cheers!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload