I have a struct, MyStruct
, which contains a map. I want to make the access to the map safe for concurrent read and write but I also want to stick to the base Map
and not use sync.Map
.
For this reason I create on MyStruct
methods for insert, delete and fetch which are protected by a mutex. The code looks like this
type MyStruct struct {
mu sync.Mutex
myMap map[string]string
}
func (myStruct *MyStruct) Add(val string) {
myStruct.mu.Lock()
myStruct.myMap[val] = val
myStruct.mu.Unlock()
}
func (myStruct *MyStruct) Remove(val string) {
myStruct.mu.Lock()
delete(myStruct.myMap, val)
myStruct.mu.Unlock()
}
func (myStruct *MyStruct) Fetch(val string) string {
myStruct.mu.Lock()
ret := delete(myStruct.myMap, val)
myStruct.mu.Unlock()
return ret
}
So far so good.
Some clients of MyStruct
though need also to loop through myStruct.myMap
and here comes my question. Which is the best design to make concurrent safe also loop operations performed not in methods of MyStruct? Currently I see 2 options
- Make the map
myMap
and the mutexmu
ofMyStruct
public and move to the clients the responsibility to make the loop thread safe. This is simple but, somehow, feels likeMyStruct
does not care too much about its clients - Keep everything private and add a method that returns a copy of the map to clients which wants safely play with it. This seems better from an "encapsulation' point of view but, at the same time, sounds a bit heavy
Is there any other possibility? Any suggestion on which design is better?