Home > Blockchain >  How to update a function's value once it's been called in golang
How to update a function's value once it's been called in golang

Time:09-22

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
}

https://go.dev/play/p/Jvx8l4F9OE8

  • Related