Reputation: 1
I have a go service running that has a map in memory, say map1. The map data (keys and values) relies on a file stored in S3. A goroutine is running to monitor this file and if there are changes, downloads the file, parses it, and creates a new map, say map2. How can I swap the contents of map1 with map2 without causing other threads from reading inconsistent data?
Below I have the rough idea of how I was thinking of solving this problem. The output of the below program is a sequence of "map1-a", followed by sequence of "map2-a". The map was swapped. Is this the best way to do this?
package main
import (
"fmt"
"time"
)
func initializeAndMonitor() *map[string]string {
map1 := make(map[string]string)
map1["a"] = "map1-a"
go func() {
time.Sleep(5 * time.Second)
map2 := make(map[string]string)
map2["a"] = "map2-a"
map1 = map2
}()
return &map1
}
func main() {
map1 := initializeAndMonitor()
for count := 0; count < 100; count = count + 1 {
fmt.Println((*map1)["a"])
time.Sleep(1 * time.Second)
}
}
Upvotes: 0
Views: 115
Reputation: 46472
This is the purpose of mutexes; wrap the reads and writes in a sync.RWMutex
:
package main
import (
"fmt"
"time"
"sync"
)
var mu = sync.RWMutex{}
func initializeAndMonitor() *map[string]string {
map1 := make(map[string]string)
map1["a"] = "map1-a"
go func() {
mu.Lock()
defer mu.Unlock()
time.Sleep(5 * time.Second)
map2 := make(map[string]string)
map2["a"] = "map2-a"
map1 = map2
}()
return &map1
}
func main() {
map1 := initializeAndMonitor()
for count := 0; count < 100; count = count + 1 {
mu.RLock()
fmt.Println((*map1)["a"])
mu.RUnlock()
time.Sleep(1 * time.Second)
}
}
Upvotes: 2