This looks concurrency safe to me too. Here's style suggestions: 

Instead of

type memoryCache struct {
 Data map[string]string
 mux  sync.Mutex
}

You could have

type memoryCache struct {
 Data map[string]string
 *sync.RWMutex
}

func (c memoryCache) Set(key string, val string) {
 defer c.Unlock()
 c.Lock()
 c.Data[key] = val
}

func (c memoryCache) Get(key string) (string, bool) {
 defer c.RUnlock()
 c.RLock()
 val, ok := c.Data[key]
 return val, ok
}

A map is already pointing to a backing data structure, so having it behind 
a pointer adds an unnecessary dereference. sync mutexes work well with 
struct embedding. RWMutex is good for cases where there may be multiple 
concurrent reads and only a few writes, although profiling is the right way 
to make performance choices like that.

Matt

On Monday, January 8, 2018 at 12:10:07 PM UTC-6, Jake Montgomery wrote:

> Your use of the sync.Mutex seems sound. At first glance, I see no 
> concurrency problems. 
>
> I would suggest running the program with the -race flag. If you make 
> memoryCache a package, then perhaps a concurrent test that can be run 
> with -race would also be good. In that case you may also want to consider 
> renaming `Data` to `data` to prevent others from directly accessing it 
> without mutex. 
>
> - Jake
>
> On Monday, January 8, 2018 at 12:38:35 PM UTC-5, Yigit Oztemel wrote:
>>
>> I have a small question about golang concurrency. I'm using go for an API 
>> project and in background, goroutines create/update caches and web requests 
>> always get cached data. We are using redis for cache and I want to store a 
>> copy of the cache in go variables so we can decrease local network traffic. 
>> Because of that I created the following example:
>>
>> https://github.com/ygto/go-memory-cache/blob/master/main.go
>>
>> func main() {
>>
>>     c := NewCache()
>>     wg := sync.WaitGroup{}
>>     wg.Add(100)
>>     for i := 0; i < 100; i++ {
>>         go func(i int) {
>>             key := fmt.Sprintf("name_%d", i)
>>             val := fmt.Sprintf("%d", i)
>>             *c.Set(key, val)*
>>             *wg.Done()*
>>         }(i)
>>     }
>>     wg.Wait()
>>     wg = sync.WaitGroup{}
>>
>>     wg.Add(100)
>>     for i := 0; i < 100; i++ {
>>         go func(i int) {
>>             key := fmt.Sprintf("name_%d", i)
>>             if data, ok := c.Get(key); ok {
>>                 fmt.Println(data)
>>             }
>>             wg.Done()
>>         }(i)
>>     }
>>     wg.Wait()
>> }
>> I highlighted the lines. In my real case, I'm using a framework and it 
>> doesn't allow me to send variables c and wg as parameters to func
>>
>> My question is, Is the above code memory safe? Can it give "concurrent 
>> map" error?
>>
>> Maybe it's not good but is it a pragmatic solution?
>>
>> Thanks
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to