具有多个用户的服务器实例

huangapple go评论115阅读模式
英文:

Server instances with multiple users

问题

我是你的中文翻译助手,以下是你提供的代码的翻译:

我刚开始学习Go,并且遇到了以下问题。我试图简化它:
我有一个服务器,例如有一个全局变量myvar。所有用户都可以通过POST请求/step1端点并将一些数据保存在该变量中,可以使用第二个端点/step2的GET请求检索该数据。在这两个调用之间,myvar的值对于该用户不应该改变。

我想知道是否有一种方法可以为每个用户实例化这个过程,因为我需要如果一个用户更改了变量,它不会影响其他用户。我不一定需要使用全局变量,这只是为了说明我想要使用这些端点做什么。

代码:

  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "github.com/gorilla/mux"
  6. "github.com/rs/cors"
  7. "fmt"
  8. )
  9. type Test struct {
  10. test string `json:"test,omitempty"`
  11. }
  12. func main() {
  13. var myvar = "test"
  14. router := mux.NewRouter()
  15. router.HandleFunc("/step1", func(w http.ResponseWriter, r *http.Request) {
  16. var test Test
  17. _ = json.NewDecoder(r.Body).Decode(&test)
  18. myvar = test.test
  19. })
  20. router.HandleFunc("/step2", func(w http.ResponseWriter, r *http.Request) {
  21. fmt.Println(myvar)
  22. })
  23. c := cors.New(cors.Options{
  24. AllowedOrigins: []string{"*"},
  25. AllowCredentials: true,
  26. AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "PATCH"},
  27. AllowedHeaders: []string{"*"},
  28. ExposedHeaders: []string{"*"},
  29. })
  30. handler := c.Handler(router)
  31. http.ListenAndServe(":8003", handler)
  32. }
英文:

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:

  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "github.com/gorilla/mux"
  6. "github.com/rs/cors"
  7. "fmt"
  8. )
  9. type Test struct {
  10. test string `json:"test,omitempty"`
  11. }
  12. func main() {
  13. var myvar = "test"
  14. router := mux.NewRouter()
  15. router.HandleFunc("/step1", func(w http.ResponseWriter, r *http.Request) {
  16. var test Test
  17. _ = json.NewDecoder(r.Body).Decode(&test)
  18. myvar = test.test
  19. })
  20. router.HandleFunc("/step2", func(w http.ResponseWriter, r *http.Request) {
  21. fmt.Println(myvar)
  22. })
  23. c := cors.New(cors.Options{
  24. AllowedOrigins: []string{"*"},
  25. AllowCredentials: true,
  26. AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "PATCH"},
  27. AllowedHeaders: []string{"*"},
  28. ExposedHeaders: []string{"*"},
  29. })
  30. handler := c.Handler(router)
  31. http.ListenAndServe(":8003", handler)
  32. }

答案1

得分: 4

请求是从多个goroutine并发地提供的。这意味着如果它们读取/写入同一个变量,对该变量的访问必须进行同步。

接下来,如果你希望每个用户都有一个不同的数据实例,你可以使用一个映射,将用户ID或名称映射到数据结构。

假设数据结构是一个结构体,例如:

  1. type customData struct {
  2. Field1 string
  3. Field2 int
  4. // 你需要的其他字段
  5. }

映射为每个用户保存一个数据结构的映射:

  1. var userDataMap = map[string]customData{}

你可以使用sync.RWMutex来保护在goroutine中读取/写入映射时:

  1. var mu = &sync.RWMutex{}

并使用上述互斥锁对映射进行同步访问:

  1. func Get(user string) customData {
  2. mu.RLock()
  3. defer mu.RUnlock()
  4. return userDataMap[user]
  5. }
  6. func Set(user string, data customData) {
  7. mu.Lock()
  8. userDataMap[user] = data
  9. mu.Unlock()
  10. }

另一种更复杂的解决方案是使用服务器端的HTTP会话。有关详细信息,请参见https://stackoverflow.com/questions/10925103/go-session-variables/35292106#35292106

英文:

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.:

  1. type customData struct {
  2. Field1 string
  3. Field2 int
  4. // Whatever fields you need
  5. }

The map holding one for each user:

  1. var userDataMap = map[string]customData{}

You may use a sync.RWMutex for protecting a map while it is read / written from a goroutine:

  1. var mu = &sync.RWMutex{}

And synchronized access to the map, using the above mutex:

  1. func Get(user string) customData {
  2. mu.RLock()
  3. defer mu.RUnlock()
  4. return userDataMap[user]
  5. }
  6. func Set(user string, data customData) {
  7. mu.Lock()
  8. userDataMap[user] = data
  9. mu.Unlock()
  10. }

Another, more sophisticated solution would be to use server side HTTP sessions. For details, see https://stackoverflow.com/questions/10925103/go-session-variables/35292106#35292106

huangapple
  • 本文由 发表于 2017年5月19日 20:36:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/44070323.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定