Skip to content

Instantly share code, notes, and snippets.

@micahhausler
Last active December 31, 2015 19:43
Show Gist options
  • Save micahhausler/2b1f2b939666ed3266c5 to your computer and use it in GitHub Desktop.
Save micahhausler/2b1f2b939666ed3266c5 to your computer and use it in GitHub Desktop.
Go map Data Race
package cache
import (
"sync"
)
// UserCache stores a concurrent-safe cache of authenticated users
type UserCache struct {
mu sync.RWMutex // guards Cache
Cache map[string]string
}
// Get gets a value from the cache, concurrent-safe
func (cache *UserCache) Get(key string) (string, bool) {
cache.mu.RLock()
defer cache.mu.RUnlock()
value, ok := cache.Cache[key]
return value, ok
}
// Set a key/value in the cache, concurrent-safe
func (cache *UserCache) Set(key, value string) {
cache.mu.Lock()
cache.Cache[key] = value
cache.mu.Unlock()
}
package cache
import (
"testing"
"time"
)
func TestUserCacheSet(t *testing.T) {
cache := UserCache{Cache: make(map[string]string)}
var tests = []struct {
key, value string
}{
{"a", "A"},
{"b", "B"},
{"c", "C"},
}
// set values
for _, test := range tests {
// incorrect!
/*
go func() {
cache.Set(test.key, test.value)
}()
*/
// corrected
go func(k, v string) {
cache.Set(k, v)
}(test.key, test.value)
}
time.Sleep(time.Second)
for _, test := range tests {
got, ok := cache.Get(test.key)
if !ok {
t.Errorf(
"cache.Get(\"%s\") returned not ok, should have been ok",
test.key,
)
}
if got != test.value && ok {
t.Errorf(
"cache.Get(\"%s\") returned \"%s\", wanted \"%s\"",
test.key, got, test.value,
)
}
}
}
$ go test -race .
==================
WARNING: DATA RACE
Read by goroutine 7:
github.com/micahhausler/cache.TestUserCacheSet.func1()
/Users/micahhausler/code/go/src/github.com/micahhausler/cache/cache_test.go:22 +0x2e
Previous write by goroutine 6:
github.com/micahhausler/cache.TestUserCacheSet()
/Users/micahhausler/code/go/src/github.com/micahhausler/cache/cache_test.go:20 +0x2a6
testing.tRunner()
/usr/local/Cellar/go/1.5.2/libexec/src/testing/testing.go:456 +0xdc
Goroutine 7 (running) created at:
github.com/micahhausler/cache.TestUserCacheSet()
/Users/micahhausler/code/go/src/github.com/micahhausler/cache/cache_test.go:23 +0x2f9
testing.tRunner()
/usr/local/Cellar/go/1.5.2/libexec/src/testing/testing.go:456 +0xdc
Goroutine 6 (running) created at:
testing.RunTests()
/usr/local/Cellar/go/1.5.2/libexec/src/testing/testing.go:561 +0xaa3
testing.(*M).Run()
/usr/local/Cellar/go/1.5.2/libexec/src/testing/testing.go:494 +0xe4
main.main()
github.com/micahhausler/cache/_test/_testmain.go:54 +0x20f
==================
==================
WARNING: DATA RACE
Read by goroutine 7:
github.com/micahhausler/cache.TestUserCacheSet.func1()
/Users/micahhausler/code/go/src/github.com/micahhausler/cache/cache_test.go:22 +0x41
Previous write by goroutine 6:
github.com/micahhausler/cache.TestUserCacheSet()
/Users/micahhausler/code/go/src/github.com/micahhausler/cache/cache_test.go:20 +0x2a6
testing.tRunner()
/usr/local/Cellar/go/1.5.2/libexec/src/testing/testing.go:456 +0xdc
Goroutine 7 (running) created at:
github.com/micahhausler/cache.TestUserCacheSet()
/Users/micahhausler/code/go/src/github.com/micahhausler/cache/cache_test.go:23 +0x2f9
testing.tRunner()
/usr/local/Cellar/go/1.5.2/libexec/src/testing/testing.go:456 +0xdc
Goroutine 6 (running) created at:
testing.RunTests()
/usr/local/Cellar/go/1.5.2/libexec/src/testing/testing.go:561 +0xaa3
testing.(*M).Run()
/usr/local/Cellar/go/1.5.2/libexec/src/testing/testing.go:494 +0xe4
main.main()
github.com/micahhausler/cache/_test/_testmain.go:54 +0x20f
==================
--- FAIL: TestUserCacheSet (1.00s)
cache_test.go:33: cache.Get("a") returned not ok, should have been ok
cache_test.go:33: cache.Get("b") returned not ok, should have been ok
FAIL
FAIL github.com/micahhausler/cache 1.016s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment