Golang的http包:Request.WithContext方法的源代码解释

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

Golang http package: Request.WithContext method src code explanation

问题

以下是http/request.go文件第290行的源代码摘录:

// WithContext返回一个浅拷贝的r,其上下文更改为ctx。提供的ctx必须非nil。
func (r *Request) WithContext(ctx context.Context) *Request {
	if ctx == nil {
		panic("nil context")
	}
	r2 := new(Request)   	//
	*r2 = *r		        // 奇怪的花招
	r2.ctx = ctx		    //
	return r2
}

我花了一个小时来理解最后4行的代码。为什么要这样做呢?难道不只是简单地写成以下这样吗:

r.ctx = ctx
return r

还是我漏掉了什么?

英文:

Following is an excerpt from source code of http/request.go line 290:

// WithContext returns a shallow copy of r with its context changed
// to ctx. The provided ctx must be non-nil.
func (r *Request) WithContext(ctx context.Context) *Request {
	if ctx == nil {
		panic("nil context")
	}
	r2 := new(Request)   	//
	*r2 = *r		        // strange gymnastics
	r2.ctx = ctx		    //
	return r2
}

I looked at it for an hour trying to understand last 4 lines. Why is that gymnastics for? Doesn't it means just the following:

r.ctx = ctx
return r

Or do I miss something?

答案1

得分: 8

让我们来分析一下这些代码行:

r2 := new(Request)

这是一个短变量声明,创建了变量 r2,并将其初始化为右侧表达式的值。右侧表达式是对内置的 new() 函数的调用,该函数为给定的类型分配内存,并返回指向该内存的指针(即该类型的零值)。

*r2 = *r

这一行将 r 指向的值赋值给 r2 指向的值。请注意,这并不是将指针值赋值,而是将指向的值赋值。由于指向的值是类型为 Request 的结构体,赋值操作会复制字段的值。

r2.ctx = ctx

由于 r2 是一个指向结构体的指针,这是 (*r2).ctx = ctx 的简写形式,它将给定的上下文值赋值给 r2 指向的值(类型为 Context 的值)的 ctx 字段。

return r2

然后返回这个 r2 指针。请注意,r2 是一个与 r 不同的指针,指向的值是一个与 r 指向的值不同且独立的请求。


如果你这样做:

r.ctx = ctx
return r

它会将上下文赋值给 r 指向的 ctx 字段,并返回相同的 r 指针。返回的值将与 r 的值相同,因此 r 和返回的值都将指向相同的 Request 值,并且都具有新的 Context 值。原始代码不会修改原始请求的 ctx(调用 WithContext() 方法的请求)。

英文:

Let's examine the lines in question:

r2 := new(Request)

This is a short variable declaration, creates the r2 variable, and initializes it with the value of the right-hand side expression, which is a call to the builtin new() function, which allocates memory for the given type, and returns a pointer to it (being the zero value of the type).

*r2 = *r

This line assigns the value pointed by r to the value pointed by r2. Note that this does not assign the pointer value, but the pointed value. Since the pointed value is of type Request which is a struct, the assignment copies the values of the fields.

r2.ctx = ctx

Since r2 is a pointer to a struct, this is a shorthand for (*r2).ctx = ctx, which assigns the given context value to the ctx field of the value (of type Context) pointed by r2.

return r2

This r2 pointer is then returned. Note that r2 is a pointer different from r, and the pointed value is a different and independent request from that pointed by r.


If you would do

r.ctx = ctx
return r

It would assign the context to the ctx field pointed by r, and this same r pointer would be returned. The returned value would be identical to the value of r, so both r and the returned value would point to the same Request value, and both would have the new Context value. The original code does not modify the ctx of the original request (the one whose WithContext() method is called).

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

发表评论

匿名网友

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

确定