I am working on a system where I have to limit concurrent connections from a particular IP. Once a connection is made, some steps are performed and then it is dropped so that other connections can be made. Below is the code where I am updating the value of a particular variable.
Link for code - http://tpcg.io/_SQZEEX
package main
import "fmt"
var addresses = make([]string, 0)
func count(rAddr string, slice *[]string) map[string]int {
dict := make(map[string]int)
*slice = append(*slice, rAddr)
for _, a := range *slice {
dict[a]
}
return dict
}
func listen() int {
var rAddr string
rAddr = "1.1.1.2"
number_of_addresses:=count(rAddr ,&addresses)
var v int
for k, v := range number_of_addresses {
fmt.Println(k, "value is", v)
if (v > 0) {
v--
fmt.Println(k, "decreased value is", v)
}
}
return v
}
func main() {
listen()
listen()
}
Upon calling the function again, the values are not refreshing for the "v" variable and the output is as below
1.1.1.2 value is 1
1.1.1.2 decreased value is 0
1.1.1.2 value is 2
1.1.1.2 decreased value is 1
Expected output:
1.1.1.2 value is 1
1.1.1.2 decreased value is 0
1.1.1.2 value is 1
1.1.1.2 decreased value is 0
What could I do so that the value is updated each time it is decreased. I understand that the value is refreshed but not sent back to the count function. How can this be achieved
CodePudding user response:
You are modifying the copy of the value you get from the map, not the value you stored in the map.
if (v > 0) {
v--
number_of_addresses[k]=v
}
However, you mentioned this is related some rate-limiting feature. If that is really the case, then instead of using a []string
to store addresses and map[string]int
to count, you should consider using a map[string]*atomic.Int64
coupled with a mutex to protect concurrent access to the map.
CodePudding user response:
Per my comments, refactor to track IP addresses via a map
i.e. a map[string]int
to track usage.
A basic implementation to get you started:
// track unique addresses via a map:
// - key: string of the IP address
// - value: usage count
var (
usageMap = make(map[string]int) //
l sync.Mutex // ensure concurrent access to map is synchronized
)
func modifyAddr(addr string, delta int) int {
l.Lock()
defer l.Unlock()
usageMap[addr] = delta
return usageMap[addr]
}
func incAddr(addr string) int { return modifyAddr(addr, 1) }
func decAddr(addr string) int { return modifyAddr(addr, -1) }
and to use:
const maxConcurrentUsage = 20
func listen() {
rAddr := "1.1.1.2"
usage := incAddr(rAddr)
defer decAddr(rAddr)
if usage > maxConcurrentUsage {
log.Printf("maximum concurrent usage exceeded (%d) for address: %q", maxConcurrentUsage, rAddr)
return
}
// handler logic goes here
}