| 12
 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
 }
 
 |