I have a map with integer values. I want to update a value and then check if the updated value exceeds a threshold.
If I didn't need to check the new value, then I would simply do
map[key] += 1
The obvious change if I want to check the new value would be:
old_val := map[key]
new_val := old_val + 1
map[key] = new_val
if (new_val > threshold) {
return
}
However, this makes two index calls to the map, which is not necessarily a constant time operation.
What I would like to do is something like:
val_p := &(map[key])
*(val_p) += 1
if (*(val_p) > threshold) {
return
}
However, GoLang maps are not addressable by design because the addresses can obviously change (although it wouldn't change in this case because I'm not altering the map).
Is there some function I could use to update the element in a map which returns the new value? Specifically for integers?
You can't do it with "simple" values for the reasons you mentioned in the question.
What you may do is store a wrapper or a pointer in the map, and so you only need to lookup the value, and you only need to do it once; changing the data is changing the pointed value which is outside of the map, so you don't have to reassign (the pointer doesn't change).
For example:
const threshold = 3
m := map[string]*int{
"one": new(int),
}
for {
p := m["one"]
fmt.Println("data=", *p)
*p++
if *p > threshold {
fmt.Println("threshold reached", *p)
break
}
}
This outputs (try it on the Go Playground):
data= 0
data= 1
data= 2
data= 3
threshold reached 4
Although note that this may not be faster due to pointer indirections. Measure if this is a critical part of your app.