I tried to find this function in Go's standard library and many other cache libraries that resemble to Java's ConcurrentMap.computeIfAbsent. I found sync.Map in the standard library which looks like what I'm looking for. I’d like to use sync.Map as a concurrent map. The problem is that the following function does not provide a defer computation as Java's ConcurrentMap does.
func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool)
LoadOrStore returns the existing value for the key if present. Otherwise, it stores and returns the given value. The loaded result is true if the value was loaded, false if stored.
It’s atomic, but the function doesn’t make sense to me. I don’t understand its purpose since I'm new to the language. I don’t know why the second param is a value not a function. Since the param will be evaluated eagerly, I have no idea how is this function useful when the value is recomputed every time anyway.
It would be much more useful IMO if the function signature is like
func (m *Map) LoadOrStore(key interface{}, f func() interface{}) (actual interface{}, loaded bool)
I mean why do we need a map when we have a value already? Pretty sure I miss something.
Let me elaborate that a bit. I don't get the reason why the function takes a value as parameter instead of a function and I'm pretty sure that I miss something. I want to get a value out of a map in a concurrent manner. When a key doesn't exist, I want to compute the value and put it into the map atomically. I know I shouldn't compare it with the ConcurrentMap in Java since the language and paradigm are different, but it could be useful to say where I'm from and it could benefit anyone who is learning Go to get a little bit of better understanding on this difference.
Here is the similar function in Java ConcurrentMap.
computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null.
The question is why LoadOrStore
function takes a value instead of a function? Any insight on why the API is designed this way would be appreciated. Also Is there a way to accomplish the same thing as I do in Java computeIfAbsent
without using an explicit lock around the map?
Updated I found that it's very easy to modify the sync.Map.LoadOrStore to take a function instead of a value.
https://play.golang.org/p/VBIaS8ZV38o
Not sure that it will work as expected though.