1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| package main
import ( "errors" "fmt" "sync"
"github.com/golang/groupcache/singleflight" )
func main() { var wg sync.WaitGroup for i := 0; i < 500; i++ { wg.Add(1) go func(n int) { var mchId = "12345" var mch, err = mchCache.GetMch(mchId) fmt.Println(n, mch, err) wg.Done() }(i) } wg.Wait() }
type MchCache struct { Mchs map[string]MchInfo sync.RWMutex g singleflight.Group }
type MchInfo struct { ID string Name string }
var mchCache MchCache var errMchNotFound = errors.New("mch not found in cache")
func (c *MchCache) GetMch(id string) (mch MchInfo, err error) { mch, err = c.getMch(id) if err == nil { return } m, err := c.g.Do(id, func() (interface{}, error) { return c.getMchFromDB(id) }) if err != nil { return } mch = m.(MchInfo) return }
func (c *MchCache) getMch(id string) (mch MchInfo, err error) { c.RLock() defer c.RUnlock() if c.Mchs == nil { c.Mchs = make(map[string]MchInfo) } if mch, ok := c.Mchs[id]; ok { return mch, nil } return mch, errMchNotFound }
func (c *MchCache) SetMch(mch MchInfo) { c.Lock() defer c.Unlock() if c.Mchs == nil { c.Mchs = make(map[string]MchInfo) } c.Mchs[mch.ID] = mch return }
func (c *MchCache) getMchFromDB(id string) (mch MchInfo, err error) { mch = MchInfo{ ID: id, Name: "星巴克", } c.SetMch(mch) return }
|