Why does http.Request.WithContext do a shallow copy?

polaris · · 438 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I don&#39;t understand the requirement that the request be shallow copied before mutating the Request.ctx field. I&#39;m hoping to implement Context-based cancellation for my own type of Request but am unsure if I need to copy my request before assigning a new Context.</p> <p><a href="https://golang.org/src/net/http/request.go?s=11679:11738#L317" rel="nofollow">https://golang.org/src/net/http/request.go?s=11679:11738#L317</a></p> <hr/>**评论:**<br/><br/>joncalhoun: <pre><p>I&#39;m not the original author, but my best guess is they wanted to support diverging code paths that all stem from the same request. Let&#39;s start by looking at a simple example: <a href="https://play.golang.org/p/jaEX4gSOvt" rel="nofollow">https://play.golang.org/p/jaEX4gSOvt</a> (shown below)</p> <pre><code>package main import ( &#34;context&#34; &#34;fmt&#34; ) type Test struct { ctx context.Context } func copy(t *Test, key, value string) { t2 := new(Test) *t2 = *t t2.ctx = context.WithValue(t.ctx, key, value) } func noCopy(t *Test, key, value string) { t.ctx = context.WithValue(t.ctx, key, value) } func main() { t := &amp;Test{context.Background()} copy(t, &#34;name&#34;, &#34;jon&#34;) fmt.Println(t.ctx.Value(&#34;name&#34;)) noCopy(t, &#34;name&#34;, &#34;hank&#34;) // because we didn&#39;t do a shallow copy, all future uses of t&#39;s ctx // will have this value set fmt.Println(t.ctx.Value(&#34;name&#34;)) } </code></pre> <p>In the second function call (<code>noCopy</code>), because we don&#39;t do a shallow copy we end up with the original <code>t</code> object having a new context value. That is why when we call <code>fmt.Println(...)</code> the second time the context has a value for the <code>&#34;name&#34;</code> key. </p> <p>This might not seem so bad, but what if the <code>noCopy</code> function had instead set a deadline intended for functions it calls instead of setting a value? Now <em>all</em> future users of the <code>t</code> variable&#39;s context have a context with a deadline that was set by <code>noCopy</code> even if it wasn&#39;t relevant to them.</p> <p>By copying you avoid this and allow each code path to set its own values and deadlines as it sees fit, and if you want one shared across them you simply set it on the <code>http.Request</code> before passing it along to both of the code paths.</p></pre>cavaliercoder: <pre><p>Great explanation, thank you. The example of setting the deadline for child function calls really concreted it for me.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

438 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传