英文:
Difference between Go's standard context package and Gorilla context package
问题
以下是翻译好的内容:
有什么区别?
哪一个更强大?
是否可以只使用标准的“context”而不使用任何第三方库来完成相同的事情?
英文:
What are the differences?
Which one is more powerful?
Can it be accomplished the same thing by using only standard context
without using any third party libraries?
答案1
得分: 14
Gorilla的context包
存储在请求生命周期中共享的值。
官方的context
包
在API边界和进程之间传递截止时间、取消信号和其他请求范围的值。
因此,从一开始就很明显,官方包做了更多的事情。但在深入细节之前,先来看一些历史:
Gorilla的context包早于官方的Go context包。它的创建是为了解决在响应HTTP请求时的一个基本问题:不同的中间件和处理程序需要能够共享请求范围的状态。例如,经过身份验证的用户的名称和用户ID,以及从数据库检索信息并在发送到模板进行解析之前的结果等。
Gorilla的context包通过一个相当丑陋的hack来实现这一点:它创建了一个以HTTP请求指针为键的映射。为了使其在并发情况下安全,它在对该映射的所有访问中都包装了互斥锁,这使得访问变慢(尽管实际上,这可能只对非常繁忙的网站有影响)。
正如前面所述,Go context包是后来出现的,目的不同。Go context包主要用于解决在不再需要时取消操作的问题。
在此之前,如果您正在提供HTTP请求,并且用户关闭了他们的Web浏览器或点击了“停止”按钮,或者他们的WiFi连接断开,您将无法得知。您的服务器将继续工作,从数据库获取值,渲染模板等,然后将结果发送回...无人接收。
或者,您的程序需要从一堆远程API获取数据,但您只愿意等待10秒。10秒后,您希望取消待处理的请求。
通过Go context包,这些事情是可能的 - 而且很容易。通过提供可取消的上下文,http库现在可以告诉您的HTTP服务器,HTTP请求已被客户端取消。或者您可以设置一个带有超时的上下文以应对后一种情况。
因此,您可以看到,这两个包旨在解决完全不同的问题。
然而,官方的Go context包还有一个额外的功能。WithValue方法允许您在上下文中传递任意数据。这确实与Gorilla的context包有相同的目的,但有点像事后补救。
现在的最佳实践是使用官方的context包。但这主要是为了取消操作。作为次要的好处,您还可以使用它来传递值 - 与您在Gorilla的context中传递的相同类型的值。
但是,如果您只是使用它来传递值,那么您将错过其90%的好处。
英文:
Gorilla's context package
> stores values shared during a request lifetime.
The official context
package
> carries deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes.
So from the outset, it's obvious that the official package does much more. But before getting into the details, some history:
Gorilla's context package predates the official Go context package. It was created to solve a fundamental problem when responding to HTTP requests: Different middlewares and handlers need to be able to share request-scoped state. Things like the authenticated user's name and user ID, as well as the results of information retrieved from a database before sending it to a template to be parsed, etc.
Gorilla's context package does this through a pretty ugly hack: It creates a map with the HTTP request pointer as a key. To make this concurrency-safe, it wraps all access to this map in mutexes, which make the access slower (although realistically, it probably only matters for very busy web sites).
The Go context package, as stated, came later, and with a different need in mind. The Go context package exists primarily to solve the problem of cancelling operations after they're no longer needed.
Before this, if you were serving an HTTP request, and the user closed their web browser or hit the 'Stop' button, or their wifi connection dropped, you would have no way of knowing. Your server would happily continue chugging along, fetching values from the database, rendering templates, etc, just to send the result back to... nobody.
Or maybe your program needs to fetch data from a bunch of remote APIs, but you're only willing to wait 10 seconds. After 10 seconds, you want to cancel the pending requests.
With the Go context package, these things are possible--and easy. By providing a cancelable context, the http library can now tell your HTTP server that the HTTP request was cancelled by the client. Or you can set a context with a timeout for the latter scenario.
So you can see, the two packages are intended to solve entirely different problems.
However, the official Go context package also has an extra feature. The WithValue method allows you to pass along arbitrary data in a context. This does serve the same purpose as Gorilla's context package, but kind of as an after thought.
Best practice these days is to use the official context package. But this should be done primarily for cancellation purposes. As a secondary benefit, you can also use it to pass along values--the same sorts of values you would pass in Gorilla's context.
But if you're only using it to pass along values, you're missing about 90% of its benefit.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论