Is it always okay to use variables concurrently in Go?

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

Is it always okay to use variables concurrently in Go?

问题

我正在编写一个小型的Web服务器程序,它需要对POST请求中的JSON进行解码。

最初,我考虑的是不要每次请求都初始化一个新的json.Decoder,而是将其作为一个全局变量,在每次调用时并发地进行解码。

作为Go的新手,这样做可以吗?是否有时候我不应该这样做,因为类可能会因为不是线程安全(我猜应该是"goroutine"安全更好)而出现问题?

英文:

I'm writing a small webserver program, and it does a lot of JSON decoding from POST requests coming in.

Initially I thought that instead of initializing a new json.Decoder every time a request comes in, I have it as a global variable that gets called on every time and decodes concurrently with goroutines.

As a newcomer to Go, is this okay? Are there times when I shouldn't be doing this and classes will freak out due to not being thread safe (I guess "goroutine" safe would be better)?

答案1

得分: 6

在Go语言中,json.NewDecoder接受一个io.Reader作为输入参数,并返回一个*json.Decoder。因此,由于每个POST请求都有不同的http.Request.Body(实现了io.Reader),所以无法重用相同的Decoder。

正如Paul Hankin所提到的,除非文档明确说明可以并发使用,否则不能同时使用Go对象。

示例:

  1. http.Client和http.Transport

    客户端和传输器可以安全地被多个goroutine并发使用,并且为了效率应该只创建一次并重复使用。

    来源

  2. Maps(映射)

    经过长时间的讨论,决定了映射的典型用法不需要从多个goroutine安全访问。

    来源

如果你询问如何重用JSON解码器以避免代码重复,你可以看看像TigertonicGo-Json-Rest这样的框架。

另外,你可以查看ffjson来加速JSON解码。

英文:

In Go, json.NewDecoder takes an io.Reader as an input parameter and returns a *json.Decoder. Hence it is not possible to reuse the same Decoder since we have a different http.Request.Body (which implements io.Reader) for each POST request.

And as mentioned by Paul Hankin, you can't use go objects concurrently unless they're documented to be safe to use concurrently.

Examples :

> 1. http.Client & http.Transport

> Clients and Transports are safe for
> concurrent use by multiple goroutines and for efficiency should only
> be created once and re-used.

Source

> 2. Maps

> After long discussion it was decided that the typical use of maps did not require safe access from multiple goroutines.

Source

If you asked about reusing JSON decoder to avoid the duplication of code you could look at frameworks like Tigertonic and Go-Json-Rest.

On a side note you could look at ffjson to speed up JSON Decoding.

答案2

得分: 2

像约翰和保罗说的那样,这不会按照你的期望工作。

如果你的主要关注是代码重复,你可能需要一个中间件。以下是一个示例,展示了你可以如何实现:

type JSONHandler func(http.ResponseWriter, *http.Request, *json.Decoder)

func JSONMiddleware(handler JSONHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		decoder := json.NewDecoder(req.Body)
		handler(w, req, decoder)
	}
}

func MyHandler(w http.ResponseWriter, req *http.Request, decoder *json.Decoder) {
	// 在这里放置你的代码,你可以访问到解码器(decoder)
}

func main() {
	http.HandleFunc("/myroute", JSONMiddleware(MyHandler))
	// ...
}

(在 playground 上查看:https://play.golang.org/p/4ZTaQguNj7)

英文:

Like John and Paul said, this won't do what you expect it to.

If your main concern is code duplication, what you probably want is a middleware. Here is an example of how you could do it

type JSONHandler func(http.ResponseWriter, *http.Request, *json.Decoder)

func JSONMiddleware(handler JSONHandler) http.HandlerFunc{
	return func(w http.ResponseWriter, req *http.Request) {
		decoder := json.NewDecoder(req.Body)
		handler(w, req, decoder)
	}
}

func MyHandler(w http.ResponseWriter, req *http.Request, decoder *json.Decoder) {
	// Put your code here, you have access to the decoder
}

func main() {
	http.HandleFunc("/myroute", JSONMiddleware(MyHandler))
	...
}

(on playground: https://play.golang.org/p/4ZTaQguNj7)

huangapple
  • 本文由 发表于 2016年4月28日 08:20:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/36903127.html
匿名

发表评论

匿名网友

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

确定