parent
378d1ee3c7
commit
009cf68312
@ -0,0 +1,42 @@ |
|||||||
|
package group |
||||||
|
|
||||||
|
import "fmt" |
||||||
|
|
||||||
|
type Counter struct { |
||||||
|
Value int |
||||||
|
} |
||||||
|
|
||||||
|
func (c *Counter) Incr() { |
||||||
|
c.Value++ |
||||||
|
} |
||||||
|
|
||||||
|
func ExampleGroup_Get() { |
||||||
|
group := NewGroup(func() interface{} { |
||||||
|
fmt.Println("Only Once") |
||||||
|
return &Counter{} |
||||||
|
}) |
||||||
|
|
||||||
|
// Create a new Counter
|
||||||
|
group.Get("pass").(*Counter).Incr() |
||||||
|
|
||||||
|
// Get the created Counter again.
|
||||||
|
group.Get("pass").(*Counter).Incr() |
||||||
|
// Output:
|
||||||
|
// Only Once
|
||||||
|
} |
||||||
|
|
||||||
|
func ExampleGroup_Reset() { |
||||||
|
group := NewGroup(func() interface{} { |
||||||
|
return &Counter{} |
||||||
|
}) |
||||||
|
|
||||||
|
// Reset the new function and clear all created objects.
|
||||||
|
group.Reset(func() interface{} { |
||||||
|
fmt.Println("reset") |
||||||
|
return &Counter{} |
||||||
|
}) |
||||||
|
|
||||||
|
// Create a new Counter
|
||||||
|
group.Get("pass").(*Counter).Incr() |
||||||
|
// Output:reset
|
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
// Package group provides a sample lazy load container.
|
||||||
|
// The group only creating a new object not until the object is needed by user.
|
||||||
|
// And it will cache all the objects to reduce the creation of object.
|
||||||
|
package group |
||||||
|
|
||||||
|
import "sync" |
||||||
|
|
||||||
|
// Group is a lazy load container.
|
||||||
|
type Group struct { |
||||||
|
new func() interface{} |
||||||
|
vals map[string]interface{} |
||||||
|
sync.RWMutex |
||||||
|
} |
||||||
|
|
||||||
|
// NewGroup news a group container.
|
||||||
|
func NewGroup(new func() interface{}) *Group { |
||||||
|
if new == nil { |
||||||
|
panic("container.group: can't assign a nil to the new function") |
||||||
|
} |
||||||
|
return &Group{ |
||||||
|
new: new, |
||||||
|
vals: make(map[string]interface{}), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Get gets the object by the given key.
|
||||||
|
func (g *Group) Get(key string) interface{} { |
||||||
|
g.RLock() |
||||||
|
v, ok := g.vals[key] |
||||||
|
if ok { |
||||||
|
g.RUnlock() |
||||||
|
return v |
||||||
|
} |
||||||
|
g.RUnlock() |
||||||
|
|
||||||
|
// slowpath for group don`t have specified key value
|
||||||
|
g.Lock() |
||||||
|
defer g.Unlock() |
||||||
|
v, ok = g.vals[key] |
||||||
|
if ok { |
||||||
|
return v |
||||||
|
} |
||||||
|
v = g.new() |
||||||
|
g.vals[key] = v |
||||||
|
return v |
||||||
|
} |
||||||
|
|
||||||
|
// Reset resets the new function and deletes all existing objects.
|
||||||
|
func (g *Group) Reset(new func() interface{}) { |
||||||
|
if new == nil { |
||||||
|
panic("container.group: can't assign a nil to the new function") |
||||||
|
} |
||||||
|
g.Lock() |
||||||
|
g.new = new |
||||||
|
g.Unlock() |
||||||
|
g.Clear() |
||||||
|
} |
||||||
|
|
||||||
|
// Clear deletes all objects.
|
||||||
|
func (g *Group) Clear() { |
||||||
|
g.Lock() |
||||||
|
g.vals = make(map[string]interface{}) |
||||||
|
g.Unlock() |
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
package group |
||||||
|
|
||||||
|
import ( |
||||||
|
"testing" |
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert" |
||||||
|
) |
||||||
|
|
||||||
|
func TestGroupGet(t *testing.T) { |
||||||
|
count := 0 |
||||||
|
g := NewGroup(func() interface{} { |
||||||
|
count++ |
||||||
|
return count |
||||||
|
}) |
||||||
|
v := g.Get("key_0") |
||||||
|
assert.Equal(t, 1, v.(int)) |
||||||
|
|
||||||
|
v = g.Get("key_1") |
||||||
|
assert.Equal(t, 2, v.(int)) |
||||||
|
|
||||||
|
v = g.Get("key_0") |
||||||
|
assert.Equal(t, 1, v.(int)) |
||||||
|
assert.Equal(t, 2, count) |
||||||
|
} |
||||||
|
|
||||||
|
func TestGroupReset(t *testing.T) { |
||||||
|
g := NewGroup(func() interface{} { |
||||||
|
return 1 |
||||||
|
}) |
||||||
|
g.Get("key") |
||||||
|
call := false |
||||||
|
g.Reset(func() interface{} { |
||||||
|
call = true |
||||||
|
return 1 |
||||||
|
}) |
||||||
|
|
||||||
|
length := 0 |
||||||
|
for range g.vals { |
||||||
|
length++ |
||||||
|
} |
||||||
|
|
||||||
|
assert.Equal(t, 0, length) |
||||||
|
|
||||||
|
g.Get("key") |
||||||
|
assert.Equal(t, true, call) |
||||||
|
} |
||||||
|
|
||||||
|
func TestGroupClear(t *testing.T) { |
||||||
|
g := NewGroup(func() interface{} { |
||||||
|
return 1 |
||||||
|
}) |
||||||
|
g.Get("key") |
||||||
|
length := 0 |
||||||
|
for range g.vals { |
||||||
|
length++ |
||||||
|
} |
||||||
|
assert.Equal(t, 1, length) |
||||||
|
|
||||||
|
g.Clear() |
||||||
|
length = 0 |
||||||
|
for range g.vals { |
||||||
|
length++ |
||||||
|
} |
||||||
|
assert.Equal(t, 0, length) |
||||||
|
} |
Loading…
Reference in new issue