I'm new to Go and I have the following problem. I tried to simplify it: I have a server which has for example a global variable myvar
. All users can POST the endpoint /step1
and save some data in the variable, which can be retrieved with a GET using the second endpoint /step2
. Between these 2 calls the value of myvar
shouldn't change for that user.
I would like to know if there is a way to instantiate this process for every user, because I need that if one user changes the variable, it doesn't affect the other users. I don't necessarily need to use the global variable, it is just to expose what I want to do with the endpoints.
Code:
package main
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
"github.com/rs/cors"
"fmt"
)
type Test struct {
test string `json:"test,omitempty"`
}
func main() {
var myvar = "test"
router := mux.NewRouter()
router.HandleFunc("/step1", func(w http.ResponseWriter, r *http.Request) {
var test Test
_ = json.NewDecoder(r.Body).Decode(&test)
myvar = test.test
})
router.HandleFunc("/step2", func(w http.ResponseWriter, r *http.Request) {
fmt.Println(myvar)
})
c := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowCredentials: true,
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "PATCH"},
AllowedHeaders: []string{"*"},
ExposedHeaders: []string{"*"},
})
handler := c.Handler(router)
http.ListenAndServe(":8003", handler)
}
Requests are served from multiple goroutines, concurrently. This means if they read/write the same variable, access to this variable must be synchronized.
Next, if you want a different instance of this data for each user, you may use a map, mapping from user ID or name to the data structure.
Let's assume the data structure is a struct, e.g.:
type customData struct {
Field1 string
Field2 int
// Whatever fields you need
}
The map holding one for each user:
var userDataMap = map[string]customData{}
You may use a sync.RWMutex
for protecting a map while it is read / written from a goroutine:
var mux = &sync.RWMutex{}
And synchronized access to the map, using the above mutex:
func Get(user string) customData {
mux.RLock()
defer mux.RUnlock()
return userDataMap[user]
}
func Set(user string, data customData) {
mux.Lock()
userDataMap[user] = data
mux.Unlock()
}
Another, more sophisticated solution would be to use server side HTTP sessions. For details, see Go session variables?