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

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

Server instances with multiple users

问题

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

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

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

代码:

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)
}
英文:

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)
}

答案1

得分: 4

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

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

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

type customData struct {
    Field1 string
    Field2 int
    // 你需要的其他字段
}

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

var userDataMap = map[string]customData{}

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

var mu = &sync.RWMutex{}

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

func Get(user string) customData {
    mu.RLock()
    defer mu.RUnlock()
    return userDataMap[user]
}

func Set(user string, data customData) {
    mu.Lock()
    userDataMap[user] = data
    mu.Unlock()
}

另一种更复杂的解决方案是使用服务器端的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.:

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 mu = &sync.RWMutex{}

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

func Get(user string) customData {
    mu.RLock()
    defer mu.RUnlock()
    return userDataMap[user]
}

func Set(user string, data customData) {
    mu.Lock()
    userDataMap[user] = data
    mu.Unlock()
}

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:

确定