Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang http package: Request.WithContext method src code explanation

Tags:

http

pointers

go

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?

like image 318
Vladimir Bauer Avatar asked Feb 06 '23 11:02

Vladimir Bauer


1 Answers

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

like image 152
icza Avatar answered May 16 '23 07:05

icza