如题。
// WithContext returns a shallow copy of r with its context changed
// to ctx. The provided ctx must be non-nil.
//
// For outgoing client request, the context controls the entire
// lifetime of a request and its response: obtaining a connection,
// sending the request, and reading the response headers and body.
//
// To create a new request with a context, use NewRequestWithContext.
// To make a deep copy of a request with a new context, use Request.Clone.
func (r *Request) WithContext(ctx context.Context) *Request {
if ctx == nil {
panic("nil context")
}
r2 := new(Request)
*r2 = *r
r2.ctx = ctx
return r2
}
1
aladdinding 2023-03-06 15:17:24 +08:00
我也有这个问题诶
|
2
fgwmlhdkkkw 2023-03-06 15:18:31 +08:00
不改变之前的引用的行为。
|
3
aladdinding 2023-03-06 15:19:15 +08:00
在 net/http 标准库中,http.Request 中的 WithContext 方法会返回一个新的 http.Request 对象,它会将原始的请求对象复制一份,然后将新的上下文信息赋值给新的请求对象。这样做的原因是为了确保新的请求对象与原始请求对象是完全独立的,以避免在并发处理请求时可能出现的竞争条件。
具体来说,WithContext 方法会浅拷贝一份原始请求对象的所有字段,包括头部、URL 、请求体等等。然后它会将新的上下文信息赋值给新的请求对象的上下文字段,这个操作是通过直接赋值来完成的。因为上下文信息通常只是一个指针类型的数据结构,因此它的复制是非常快速和低成本的,因此可以直接进行赋值操作。 通过浅拷贝一份请求对象,可以确保新的请求对象与原始请求对象是独立的。这意味着对新的请求对象的任何修改都不会影响原始请求对象,反之亦然。这在处理并发请求时非常重要,因为多个并发请求可能会同时修改同一个请求对象,这可能会导致不可预料的结果。通过确保每个请求对象都是独立的,可以避免这种情况的发生,从而提高程序的稳定性和可靠性。 FROM ChatGPT |
4
Frankcox 2023-03-06 16:31:37 +08:00
|
5
ranleng 2023-03-06 17:14:59 +08:00
> Request is explicitly immutable. That's why we have Request.WithContext.
|
6
lesismal 2023-03-06 17:48:18 +08:00 2
@Frankcox 我来啦,感谢 at !
当初提这个 pr 是因为我的 nbio 实现的 http 兼容标准库,这涉及到 Request 的 context 字段,每个请求的 context 应该是共用一个全局的,这样当全局的 context 退出(比如进程退出、cancel 时),这个 request 的 handler 中使用这个 context 就可以一块退出(比如使用 Mysql 时传入这个 context )。但这个字段不是导出的,所以没有办法直接设置。 由于标准库规则严格、不肯开放这个字段导出,至少对于官方而言,他们不考虑 nbio 要解决的海量并发连接数写成数量、内存开销、GC 等问题,所以官方也确实不需要开放导出。 无奈只能使用魔法了,预先用 WithContext 生成了一个带有公共 context 的 Request ,后面创建新 Request 时 *newReq = *reqWithCtx 整体赋值,就避过没导出不能设置的问题了。不过虽然能用,毕竟 Request 结构体有点大,这么做能用但不划算,凑合用吧,毕竟我也支持官方不随意放权。。。 :joy: |
7
macscsbf OP @aladdinding 谢谢
|