{"id":10006609,"date":"2022-09-27T02:43:00","date_gmt":"2022-09-26T18:43:00","guid":{"rendered":"https:\/\/ityet.com\/?p=10006609"},"modified":"2022-09-27T02:43:00","modified_gmt":"2022-09-26T18:43:00","slug":"%e8%bd%bb%e6%9d%be%e4%b8%8a%e6%89%8b%ef%bc%81%e6%89%8b%e6%8a%8a%e6%89%8b%e5%b8%a6%e4%bd%a0%e6%8e%8c%e6%8f%a1%e4%bb%8econtext%e5%88%b0go%e8%ae%be%e8%ae%a1%e7%90%86%e5%bf%b5","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10006609","title":{"rendered":"\u8f7b\u677e\u4e0a\u624b\uff01\u624b\u628a\u624b\u5e26\u4f60\u638c\u63e1\u4eceContext\u5230go\u8bbe\u8ba1\u7406\u5ff5"},"content":{"rendered":"<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042547166\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u5bfc\u8bed\u00a0|\u00a0\u672c\u6587\u63a8\u9009\u81ea\u817e\u8baf\u4e91\u5f00\u53d1\u8005\u793e\u533a-\u3010\u6280\u601d\u5e7f\u76ca \u00b7 \u817e\u8baf\u6280\u672f\u4eba\u539f\u521b\u96c6\u3011\u4e13\u680f\u3002\u8be5\u4e13\u680f\u662f\u817e\u8baf\u4e91\u5f00\u53d1\u8005\u793e\u533a\u4e3a\u817e\u8baf\u6280\u672f\u4eba\u4e0e\u5e7f\u6cdb\u5f00\u53d1\u8005\u6253\u9020\u7684\u5206\u4eab\u4ea4\u6d41\u7a97\u53e3\u3002\u680f\u76ee\u9080\u7ea6\u817e\u8baf\u6280\u672f\u4eba\u5206\u4eab\u539f\u521b\u7684\u6280\u672f\u79ef\u6dc0\uff0c\u4e0e\u5e7f\u6cdb\u5f00\u53d1\u8005\u4e92\u542f\u8fea\u5171\u6210\u957f\u3002\u672c\u6587\u4f5c\u8005\u662f\u817e\u8baf\u540e\u7aef\u5f00\u53d1\u5de5\u7a0b\u5e08\u9648\u96ea\u950b\u3002<br \/>context\u5305\u6bd4\u8f83\u5c0f\uff0c\u662f\u9605\u8bfb\u6e90\u7801\u6bd4\u8f83\u7406\u60f3\u7684\u4e00\u4e2a\u5165\u624b\uff0c\u5e76\u4e14\u91cc\u9762\u4e5f\u6db5\u76d6\u4e86\u8bb8\u591ago\u8bbe\u8ba1\u7406\u5ff5\u53ef\u4ee5\u5b66\u4e60\u3002<br \/>go\u7684Context\u4f5c\u4e3ago\u5e76\u53d1\u65b9\u5f0f\u7684\u4e00\u79cd\uff0c\u65e0\u8bba\u662f\u5728\u6e90\u7801net\/http\u4e2d\uff0c\u5f00\u6e90\u6846\u67b6\u4f8b\u5982gin\u4e2d\uff0c\u8fd8\u662f\u5185\u90e8\u6846\u67b6trpc-go\u4e2d\u90fd\u662f\u4e00\u4e2a\u6bd4\u8f83\u91cd\u8981\u7684\u5b58\u5728\uff0c\u800c\u6574\u4e2a context \u7684\u5b9e\u73b0\u4e5f\u5c31\u4e0d\u5230600\u884c\uff0c\u6240\u4ee5\u4e5f\u60f3\u501f\u7740\u8fd9\u6b21\u673a\u4f1a\u6765\u5b66\u4e60\u5b66\u4e60\uff0c\u672c\u6587\u57fa\u4e8ego 1.18.4\u3002\u8bdd\u4e0d\u591a\u8bf4\uff0c\u4f8b\uff1a<br \/>\u4e3a\u4e86\u4f7f\u53ef\u80fd\u5bf9context\u4e0d\u592a\u719f\u6089\u7684\u540c\u5b66\u6709\u4e2a\u719f\u6089\uff0c\u5148\u6765\u4e2aexample \uff0c\u6458\u81ea\u6e90\u7801\uff1a<\/p>\n<p>\u6211\u4eec\u5229\u7528WithCancel\u521b\u5efa\u4e00\u4e2a\u53ef\u53d6\u6d88\u7684Context\uff0c\u5e76\u4e14\u904d\u5386\u9891\u9053\u8f93\u51fa\uff0c\u5f53 n==5\u65f6\uff0c\u4e3b\u52a8\u8c03\u7528cancel\u6765\u53d6\u6d88\u3002<br \/>\u800c\u5728gen func\u4e2d\u6709\u4e2a\u534f\u7a0b\u6765\u76d1\u542cctx\u5f53\u76d1\u542c\u5230ctx.Done\uff08\uff09\u5373\u88ab\u53d6\u6d88\u540e\u5c31\u9000\u51fa\u534f\u7a0b\u3002<\/p>\n<pre><code>func main(){\n\ngen := func(ctx context.Context) &lt;-chan int {\n\ndst := make(chan int)\n\nn := 1\n\ngo func() {\n\nfor {\n\nselect {\n\ncase &lt;-ctx.Done():\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0close(dst)\n\nreturn \/\/ returning not to leak the goroutine\n\ncase dst &lt;- n:\n\nn++\n\n}\n\n}\n\n}()\n\nreturn dst\n\n}\n\n\u00a0\n\nctx, cancel := context.WithCancel(context.Background())\n\n\/\/ defer cancel() \/\/ \u5b9e\u9645\u4f7f\u7528\u4e2d\u5e94\u8be5\u5728\u8fd9\u91cc\u8c03\u7528 cancel\n\n\u00a0\n\nfor n := range gen(ctx) {\n\nfmt.Println(n)\n\nif n == 5 {\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cancel() \/\/ \u8fd9\u91cc\u4e3a\u4e86\u4f7f\u4e0d\u719f\u6089 go \u7684\u66f4\u80fd\u660e\u767d\u5728\u8fd9\u91cc\u8c03\u7528\u4e86 cancel()\n\nbreak\n\n}\n\n}\n\n\/\/ Output:\n\n\/\/ 1\n\n\/\/ 2\n\n\/\/ 3\n\n\/\/ 4\n\n\/\/ 5\n\n}<\/code><\/pre>\n<p>\u8fd9\u662f\u6700\u57fa\u672c\u7684\u4f7f\u7528\u65b9\u6cd5\u3002<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042547167\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2>\u6982\u89c8<\/h2>\n<p>\u5bf9\u4e8econtext\u5305\u5148\u4e0a\u4e00\u5f20\u56fe\uff0c\u4fbf\u4e8e\u5927\u5bb6\u6709\u4e2a\u521d\u6b65\u4e86\u89e3\uff08\u5185\u90e8\u51fd\u6570\u5e76\u672a\u5168\u5217\u4e3e\uff0c\u540e\u7eed\u4f1a\u9010\u4e00\u8bb2\u89e3\uff09\uff1a<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042547168\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p>\u6700\u91cd\u8981\u7684\u5c31\u662f\u53f3\u8fb9\u7684\u63a5\u53e3\u90e8\u5206\uff0c\u53ef\u4ee5\u770b\u5230\u6709\u51e0\u4e2a\u6bd4\u8f83\u91cd\u8981\u7684\u63a5\u53e3\uff0c\u4e0b\u9762\u9010\u4e00\u6765\u8bf4\u4e0b\uff1a<\/p>\n<pre><code>type Context interface{\n        Deadline() (deadline time.Time, ok bool)\n        Done() &lt;-chan struct{}        Err() error\n        Value(key any) any\n}<\/code><\/pre>\n<p>\u9996\u5148\u5c31\u662fContext\u63a5\u53e3\uff0c\u8fd9\u662f\u6574\u4e2acontext\u5305\u7684\u6838\u5fc3\u63a5\u53e3\uff0c\u5c31\u5305\u542b\u4e86\u56db\u4e2a method\uff0c\u5206\u522b\u662f\uff1a<\/p>\n<pre><code>Deadline() (deadline time.Time, ok bool) \/\/ \u83b7\u53d6 deadline \u65f6\u95f4\uff0c\u5982\u679c\u6ca1\u6709\u7684\u8bdd ok \u4f1a\u8fd4\u56de false<\/code><\/pre>\n<pre><code>Done() &lt;-chan struct{} \/\/ \u8fd4\u56de\u7684\u662f\u4e00\u4e2a channel \uff0c\u7528\u6765\u5e94\u7528\u76d1\u542c\u4efb\u52a1\u662f\u5426\u5df2\u7ecf\u5b8c\u6210<\/code><\/pre>\n<pre><code>Err() error \/\/ \u8fd4\u56de\u53d6\u6d88\u539f\u56e0 \u4f8b\u5982\uff1aCanceled\/DeadlineExceeded\nValue(key any) any \/\/ \u6839\u636e\u6307\u5b9a\u7684 key \u83b7\u53d6\u662f\u5426\u5b58\u5728\u5176 value \u6709\u5219\u8fd4\u56de<\/code><\/pre>\n<p>\u53ef\u4ee5\u770b\u5230\u8fd9\u4e2a\u63a5\u53e3\u975e\u5e38\u6e05\u6670\u7b80\u5355\u660e\u4e86\uff0c\u5e76\u4e14\u6ca1\u6709\u8fc7\u591a\u7684Method\uff0c\u8fd9\u4e5f\u662fgo \u8bbe\u8ba1\u7406\u5ff5\uff0c\u63a5\u53e3\u5c3d\u91cf\u7b80\u5355\u3001\u5c0f\u5de7\uff0c\u901a\u8fc7\u7ec4\u5408\u6765\u5b9e\u73b0\u4e30\u5bcc\u7684\u529f\u80fd\uff0c\u540e\u9762\u4f1a\u770b\u5230\u5982\u4f55\u7ec4\u5408\u7684\u3002<\/p>\n<p>\u518d\u6765\u770b\u53e6\u4e00\u4e2a\u63a5\u53e3canceler\uff0c\u8fd9\u662f\u4e00\u4e2a\u53d6\u6d88\u63a5\u53e3\uff0c\u5176\u4e2d\u4e00\u4e2a\u975e\u5bfc\u51fa method cancel\uff0c\u63a5\u6536\u4e00\u4e2abool\u548c\u4e00\u4e2aerror\uff0cbool\u7528\u6765\u51b3\u5b9a\u662f\u5426\u5c06\u5176\u4ece\u7236Context\u4e2d\u79fb\u9664\uff0cerr\u7528\u6765\u6807\u660e\u88ab\u53d6\u6d88\u7684\u539f\u56e0\u3002\u8fd8\u6709\u4e2aDone\uff08\uff09\u548cContext\u63a5\u53e3\u4e00\u6837\uff0c\u8fd9\u4e2a\u63a5\u53e3\u4e3a\u4f55\u8fd9\u4e48\u8bbe\u8ba1\uff0c\u540e\u9762\u518d\u63ed\u6653\u3002<\/p>\n<pre><code>type canceler interface{  \ncancel(removeFromParent bool, err error)  \nDone() &lt;-chan struct{}\n}<\/code><\/pre>\n<p>\u63a5\u4e0b\u6765\u770b\u8fd9\u4e24\u4e2a\u63a5\u53e3\u7684\u5b9e\u73b0\u8005\u90fd\u6709\u8c01\uff0c\u9996\u5148Context\u76f4\u63a5\u5b9e\u73b0\u8005\u6709 <em>valueCtx\uff08\u6bd4\u8f83\u7b80\u5355\u653e\u6700\u540e\u8bb2\uff09\u548c<\/em>emptyCtx<\/p>\n<p>\u800ccanceler\u76f4\u63a5\u5b9e\u73b0\u8005\u6709<em>cancelCtx\u548c<\/em>timerCtx \uff0c\u5e76\u4e14\u8fd9\u4e24\u4e2a\u540c\u65f6\u4e5f\u5b9e\u73b0\u4e86Context\u63a5\u53e3\uff08\u8bb0\u4f4f\u6211\u524d\u9762\u8bf4\u5f97\u53e6\u5916\u4e24\u4e2a\u662f\u76f4\u63a5\u5b9e\u73b0\uff0c\u8fd9\u4fe9\u662f\u5d4c\u5957\u63a5\u53e3\u5b9e\u73b0\u677e\u8026\u5408\uff0c\u540e\u9762\u518d\u8bf4\u5177\u4f53\u597d\u5904\uff09\uff0c\u4e0b\u9762\u9010\u4e00\u8bb2\u89e3\u6bcf\u4e2a\u5b9e\u73b0\u3002<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042547169\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2>\u7a7a\u7684<\/h2>\n<p>\u89c1\u540d\u77e5\u4e49\uff0c\u8fd9\u662f\u4e00\u4e2a\u7a7a\u5b9e\u73b0\uff0c\u4e8b\u5b9e\u4e5f\u7684\u786e\u5982\u6b64\uff0c\u53ef\u4ee5\u770b\u5230\u5565\u5565\u90fd\u6ca1\u6709\uff0c\u5c31\u662f\u4e2a\u7a7a\u5b9e\u73b0\uff0c\u4e3a\u4f55\u8981\u5199\u5462\uff1f<\/p>\n<pre><code>type emptyCtx int\nfunc (*emptyCtx) Deadline() (deadline time.Time, ok bool) {  return}\nfunc (*emptyCtx) Done() &lt;-chan struct{} {  return nil}\nfunc (*emptyCtx) Err() error {  return nil}\nfunc (*emptyCtx) Value(key any) any {  return nil}\nfunc (e *emptyCtx) String() string {  switch e {  case background:    return &quot;context.Background&quot;  case todo:    \nreturn &quot;context.TODO&quot;  }  return &quot;unknown empty Context&quot;}<\/code><\/pre>\n<p>\u518d\u5f80\u4e0b\u8bfb\u6e90\u7801\u4f1a\u53d1\u73b0\u4e24\u4e2a\u6709\u610f\u601d\u7684\u53d8\u91cf\uff0c\u5e95\u5c42\u4e00\u6a21\u4e00\u6837\uff0c\u4e00\u4e2a\u53d6\u540d\u53eb background\uff0c\u4e00\u4e2a\u53d6\u540d\u53ebtodo\uff0c\u4e3a\u4f55\u5462\uff1f\u8010\u5fc3\u7684\u53ef\u4ee5\u770b\u770b\u89e3\u91ca\uff0c\u5176\u5b9e\u662f\u4e3a\u4e86\u65b9\u4fbf\u5927\u5bb6\u533a\u5206\u4f7f\u7528\uff0c\u80cc\u666f\u00a0\u662f\u5728\u5165\u53e3\u5904\u6765\u4f20\u9012\u6700\u521d\u59cb\u7684context\uff0c\u800ctodo \u5219\u662f\u5f53\u4f60\u4e0d\u77e5\u9053\u7528\u5565\uff0c\u6216\u8005\u4f60\u7684\u51fd\u6570\u867d\u7136\u63a5\u6536ctontext\u53c2\u6570\uff0c\u4f46\u662f\u5e76\u6ca1\u6709\u505a\u4efb\u4f55\u5b9e\u73b0\u65f6\uff0c\u90a3\u4e48\u5c31\u4f7f\u7528todo\u5373\u53ef\u3002\u540e\u7eed\u5982\u679c\u6709\u5177\u4f53\u5b9e\u73b0\u518d\u4f20\u5165\u5177\u4f53\u7684\u4e0a\u4e0b\u6587\u3002\u6240\u4ee5\u4e0a\u9762\u624d\u5b9a\u4e49\u4e86\u4e00\u4e2a\u7a7a\u5b9e\u73b0\uff0c\u5c31\u4e3a\u4e86\u7ed9\u8fd9\u4fe9\u4f7f\u7528\u5462\uff0c\u8fd9\u4fe9\u4e5f\u662f\u6211\u4eec\u6700\u5e38\u5728\u5165\u53e3\u5904\u4f7f\u7528\u7684\u3002<\/p>\n<pre><code>var (\n\n\u00a0\u00a0background = new(emptyCtx)\n\n\u00a0\u00a0todo \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0= new(emptyCtx)\n\n)\n\n\u00a0\n\n\/\/ Background returns a non-nil, empty Context. It is never canceled, has no\n\n\/\/ values, and has no deadline. It is typically used by the main function,\n\n\/\/ initialization, and tests, and as the top-level Context for incoming\n\n\/\/ requests.\n\nfunc Background() Context {\n\n\u00a0\u00a0return background\n\n}\n\n\u00a0\n\n\/\/ TODO returns a non-nil, empty Context. Code should use context.TODO when\n\n\/\/ it's unclear which Context to use or it is not yet available (because the\n\n\/\/ surrounding function has not yet been extended to accept a Context\n\n\/\/ parameter).\n\nfunc TODO() Context {\n\n\u00a0\u00a0return todo\n\n}<\/code><\/pre>\n<p>\u4e0b\u9762\u518d\u770b\u770b\u5177\u4f53\u7684\u5b9a\u4e49\u5427\u3002<\/p>\n<h2>cancelCtx\u4e0etimerCtx\u3001valueCtx<\/h2>\n<pre><code>type cancelCtx struct{\n\n\u00a0\u00a0Context\n\n\u00a0\u00a0mu \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0sync.Mutex \u00a0\/\/ \u9501\u4f4f\u4e0b\u9762\u5b57\u6bb5\u7684\u64cd\u4f5c\n\n\u00a0\u00a0\/\/ \u5b58\u653e\u7684\u662f chan struct{}, \u61d2\u521b\u5efa,\n\n\u00a0\u00a0\/\/ \u00a0\u53ea\u6709\u7b2c\u4e00\u6b21\u88ab cancel \u65f6\u624d\u4f1a\u5173\u95ed\n\n\u00a0\u00a0done \u00a0\u00a0\u00a0\u00a0atomic.Value \u00a0\n\n\u00a0\u00a0\/\/ children \u5b58\u653e\u7684\u662f\u5b50 Context canceler \uff0c\u5e76\u4e14\u5f53\u7b2c\u4e00\u6b21\u88ab cancel \u65f6\u4f1a\u88ab\n\n\u00a0\u00a0\/\/ \u8bbe\u4e3a nil\n\n\u00a0\u00a0children map[canceler]struct{}\n\n\u00a0\u00a0\/\/ \u00a0\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528 cancel \u65f6\uff0c\u4f1a\u88ab\u8bbe\u7f6e\n\n\u00a0\u00a0err \u00a0\u00a0\u00a0\u00a0\u00a0error \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\n\n}\n\n\u00a0\n\ntype timerCtx struct{\n\n\u00a0cancelCtx\n\n\u00a0timer *time.Timer \/\/ \u5b9a\u65f6\u5668\uff0c\u7528\u6765\u76d1\u542c\u662f\u5426\u8d85\u65f6\u8be5\u53d6\u6d88\n\n\u00a0deadline time.Time \/\/ \u7ec8\u6b62\u65f6\u95f4\n\n}\n\n\u00a0\n\ntype valueCtx struct {\n\n\u00a0Context\n\n\u00a0key, val any\n\n}<\/code><\/pre>\n<p>\u8fd9\u91cc\u5c31\u770b\u51fa\u6765\u4e3a\u4f55cancelCtx\u4e3a\u975e\u5bfc\u51fa\u4e86\uff0c\u56e0\u4e3a\u5b83\u901a\u8fc7\u5185\u5d4cContext\u63a5\u53e3\u4e5f\u4e5f\u662f\u5b9e\u73b0\u4e86Context\u7684\u3002\u5e76\u4e14\u901a\u8fc7\u8fd9\u79cd\u65b9\u5f0f\u5b9e\u73b0\u4e86\u677e\u8026\u5408\uff0c\u53ef\u4ee5\u901a\u8fc7 WithCancel\uff08\u7236Context\uff09 \uff08ctx Context\uff0ccancel CancelFunc\uff09 \u6765\u4f20\u9012\u4efb\u4f55\u81ea\u5b9a\u4e49\u7684Context\u5b9e\u73b0\u3002<\/p>\n<p>\u800ctimerCtx\u662f\u5d4c\u5957\u7684cancelCtx\uff0c\u540c\u6837\u4ed6\u4e5f\u53ef\u4ee5\u540c\u65f6\u8c03\u7528Context\u63a5\u53e3\u6240\u6709 method\u4e0ecancelCtx\u6240\u6709method \uff0c\u5e76\u4e14\u8fd8\u53ef\u4ee5\u91cd\u5199\u90e8\u5206\u65b9\u6cd5\u3002\u800c valueCtx\u548c\u4e0a\u9762\u4e24\u4e2a\u6bd4\u8f83\u72ec\u7acb\uff0c\u6240\u4ee5\u76f4\u63a5\u5d4c\u5957\u7684Context\u3002<\/p>\n<p>\u8fd9\u91cc\u5e94\u8be5\u4e5f\u770b\u660e\u767d\u4e86\u4e3a\u4f55canceler\u4e3a\u4f55\u4e00\u4e2a\u53ef\u5bfc\u51faDone\u4e00\u4e2a\u4e0d\u53ef\u5bfc\u51fa cancel\uff0cDone\u662f\u91cd\u5199Context\u7684method\u4f1a\u7531\u4e0a\u5c42\u8c03\u7528\uff0c\u6240\u4ee5\u8981\u53ef\u5bfc\u51fa\uff0c cancel\u5219\u662f\u7531return func\uff08\uff09{c.cancel\uff08false\uff0cDeadlineExeceed\uff09 \u7c7b\u4f3c\u7684\u5c01\u88c5\u5bfc\u51fa\uff0c\u6240\u4ee5\u4e0d\u5e94\u8be5\u5bfc\u51fa\u3002<\/p>\n<p>\u8fd9\u662fgo\u4e2d\u63a8\u5d07\u7684\u901a\u8fc7\u7ec4\u5408\u800c\u975e\u7ee7\u627f\u6765\u7f16\u5199\u4ee3\u7801\u3002\u5176\u4e2d\u5b57\u6bb5\u89e3\u91ca\u6211\u5df2\u5728\u540e\u9762\u6ce8\u660e\uff0c\u540e\u9762\u4e5f\u4f1a\u8bb2\u5230\u3002\u770b\u61c2\u4e86\u5927\u7684\u4e00\u4e2a\u8bbe\u8ba1\u7406\u5ff5\uff0c\u4e0b\u9762\u6211\u4eec\u5c31\u9010\u4e00\u51fb\u7834\uff0c\u901a\u8fc7\u4e0a\u9762\u53ef\u4ee5\u770b\u5230timerCtx\u5176\u5b9e\u662f\u590d\u7528\u4e86cancelCtx\u80fd\u529b\uff0c\u6240\u4ee5cancelCtx\u6700\u4e3a\u91cd\u8981\uff0c\u4e0b\u9762\u6211\u4eec\u5c31\u5148\u5c06cancelCtx\u5b9e\u73b0\u3002<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042547170\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2>\u53d6\u6d88<\/h2>\n<p>\u5b83\u975e\u5bfc\u51fa\uff0c\u662f\u901a\u8fc7\u4e00\u4e2a\u65b9\u6cd5\u6765\u76f4\u63a5\u8fd4\u56deContext\u7c7b\u578b\u7684\uff0c\u8fd9\u4e5f\u662fgo\u7406\u5ff5\u4e4b\u4e00\uff0c\u4e0d\u66b4\u9732\u5b9e\u73b0\u8005\uff0c\u53ea\u66b4\u9732\u63a5\u53e3\uff08\u524d\u63d0\u662f\u5b9e\u73b0\u8005\u4e2d\u7684\u53ef\u5bfc\u51famethod\u4e0d\u5305\u542b\u63a5\u53e3\u4e4b\u5916\u7684method\uff0c \u5426\u5219\u5bfc\u51fa\u7684method\u5916\u9762\u4e5f\u65e0\u6cd5\u8c03\u7528\uff09\u3002<\/p>\n<p>\u5148\u770b\u770b\u5916\u90e8\u6784\u9020\u51fd\u6570WithCancel\uff0c<\/p>\n<ul>\n<li>\u5148\u5224\u65adparent\u662f\u5426\u4e3anil\uff0c\u5982\u679c\u4e3anil\u5c31panic\uff0c\u8fd9\u662f\u4e3a\u4e86\u907f\u514d\u5230\u5904\u5224\u65ad\u662f\u5426\u4e3anil\u3002\u6240\u4ee5\u6c38\u8fdc\u4e0d\u8981\u4f7f\u7528nil\u6765\u4f5c\u4e3a\u4e00\u4e2aContext\u4f20\u9012\u3002<\/li>\n<\/ul>\n<ul>\n<li>\u63a5\u7740\u5c06\u7236Context\u5c01\u88c5\u5230cancelCtx\u5e76\u8fd4\u56de\uff0c\u8fd9\u6ca1\u5565\u8bf4\u5f97\uff0c\u867d\u7136\u53ea\u6709\u4e00\u884c\u4ee3\u7801\uff0c\u4f46\u662f\u591a\u5904\u4f7f\u7528\uff0c\u6240\u4ee5\u505a\u4e86\u5c01\u88c5\uff0c\u5e76\u4e14\u540e\u7eed\u5982\u679c\u8981\u66f4\u6539\u884c\u4e3a\u8c03\u7528\u8005\u4e5f\u65e0\u9700\u66f4\u6539\u3002\u5f88\u65b9\u4fbf\u3002<\/li>\n<\/ul>\n<ul>\n<li>\u8c03\u7528propagateCancel\uff0c\u8fd9\u4e2a\u51fd\u6570\u4f5c\u7528\u5c31\u662f\u5f53parent\u662f\u53ef\u4ee5\u88ab\u53d6\u6d88\u7684\u65f6\u5019\u5c31\u4f1a\u5bf9\u5b50Context\u4e5f\u8fdb\u884c\u53d6\u6d88\u7684\u53d6\u6d88\u6216\u8005\u51c6\u5907\u53d6\u6d88\u52a8\u4f5c\u3002<\/li>\n<\/ul>\n<ul>\n<li>\u8fd4\u56deContext\u4e0eCancelFunc type &gt;CancelFunc func\uff08\uff09\u5c31\u662f\u4e00\u4e2a type func\u522b\u540d\uff0c\u5e95\u5c42\u5c01\u88c5\u7684\u662fc.cancel\u65b9\u6cd5\uff0c\u4e3a\u4f55\u8fd9\u4e48\u505a\u5462\uff1f\u8fd9\u662f\u4e3a\u4e86\u7ed9\u4e0a\u5c42\u5e94\u7528\u4e00\u4e2a\u7edf\u4e00\u7684\u8c03\u7528\uff0ccancelCtx\u4e0etimerCtx\u4ee5\u53ca\u5176\u4ed6\u53ef\u4ee5\u5b9e\u73b0\u4e0d\u540c\u7684cancel\u4f46\u662f\u5bf9\u4e0a\u5c42\u662f\u900f\u660e\u5e76\u4e14\u4e00\u81f4\u7684\u884c\u4e3a\u5c31\u53ef\u3002\u8fd9\u4e2afunc\u5e94\u8be5\u662f\u534f\u7a0b\u5b89\u5168\u5e76\u4e14\u591a\u6b21\u8c03\u7528\u53ea\u6709\u7b2c\u4e00\u6b21\u8c03\u7528\u624d\u6709\u6548\u679c\u3002<\/li>\n<\/ul>\n<pre><code>func WithCancel(parent Context) (ctx Context, cancel CancelFunc){\n\n\u00a0\u00a0\u00a0\u00a0\u00a0if parent == nil {\n\n\u00a0\u00a0\u00a0\u00a0panic(&quot;cannot create context from nil parent&quot;)\n\n\u00a0\u00a0}\n\n\u00a0\u00a0c := newCancelCtx(parent)\n\n\u00a0\u00a0propagateCancel(parent, &amp;c)\n\n\u00a0\u00a0return&amp;c, func() { c.cancel(true, Canceled) }\n\n}\n\n\u00a0\n\nfunc newCancelCtx(parent Context) cancelCtx {\n\n\u00a0return cancelCtx{Context: parent}\n\n}<\/code><\/pre>\n<p>\u63a5\u4e0b\u6765\u5c31\u6765\u5230\u6bd4\u8f83\u91cd\u8981\u7684func\u00a0 propagateCancel\uff0c\u6211\u4eec\u770b\u770b\u5b83\u505a\u4e86\u5565\uff0c<\/p>\n<p>\u9996\u5148\u662f\u5224\u65ad\u7236context\u7684Done\uff08\uff09\u65b9\u6cd5\u8fd4\u56de\u7684channel\u662f\u5426\u4e3anil\uff0c\u5982\u679c\u662f\u5219\u76f4\u63a5\u8fd4\u56de\u5565\u4e5f\u4e0d\u505a\u4e86\u3002\u8fd9\u662f\u56e0\u4e3a\u7236Context\u4ece\u6765\u4e0d\u4f1a\u88ab\u53d6\u6d88\u7684\u8bdd\uff0c\u90a3\u5c31\u6ca1\u5fc5\u8981\u8fdb\u884c\u4e0b\u9762\u52a8\u4f5c\u3002\u8fd9\u4e5f\u8868\u540d\u6211\u4eec\u4f7f\u7528.\u4e0e\u732b\uff08\u4e0a\u4e0b\u6587\u3002Background\uff08\uff09\uff09 \u8fd9\u4e2a\u51fd\u6570\u662f\u4e0d\u4f1a\u505a\u4efb\u4f55\u52a8\u4f5c\u7684\u3002<\/p>\n<pre><code> done := parent.Done()\n\u00a0\u00a0if done == nil {\n\u00a0\u00a0\u00a0\u00a0return \/\/ parent is never canceled\n\u00a0\u00a0}<\/code><\/pre>\n<p>\u63a5\u4e0b\u91cc\u5c31\u662f\u4e00\u4e2aselect \uff0c\u5982\u679c\u7236Context\u5df2\u7ecf\u88ab\u53d6\u6d88\u4e86\u7684\u8bdd\uff0c\u90a3\u5c31\u76f4\u63a5\u53d6\u6d88\u5b50Context\u5c31\u597d\u4e86\uff0c\u8fd9\u4e2a\u4e5f\u7406\u6240\u5e94\u5f53\uff0c\u7236\u4eb2\u90fd\u88ab\u53d6\u6d88\u4e86\uff0c\u513f\u5b50\u5f53\u7136\u4e5f\u5e94\u8be5\u53d6\u6d88\uff0c\u6ca1\u6709\u5b58\u5728\u5fc5\u8981\u4e86\u3002<\/p>\n<pre><code>select {\n\u00a0\u00a0case &lt;-done:\n\u00a0\u00a0\u00a0\u00a0\/\/ parent is already canceled\n\u00a0\u00a0\u00a0\u00a0child.cancel(false, parent.Err())\n\u00a0\u00a0\u00a0\u00a0return\n\u00a0\u00a0default:\n\u00a0\u00a0}<\/code><\/pre>\n<p>\u5982\u679c\u7236 Context \u6ca1\u6709\u88ab\u53d6\u6d88\uff0c\u8fd9\u91cc\u5c31\u4f1a\u505a\u4e2a\u5224\u65ad\uff0c<\/p>\n<ul>\n<li>\u770b\u770bparent\u662f\u5426\u662f\u4e00\u4e2a*cancelCtx\uff0c\u5982\u679c\u662f\u7684\u8bdd\u5c31\u8fd4\u56de\u5176p\uff0c\u518d\u6b21\u68c0\u67e5 p.err\u662f\u5426\u4e3anil\uff0c\u5982\u679c\u4e0d\u4e3anil\u5c31\u8bf4\u660eparent\u88ab\u53d6\u6d88\uff0c\u63a5\u7740\u53d6\u6d88 \u5b50 Context\uff0c\u5982\u679c\u6ca1\u88ab\u53d6\u6d88\u7684\u8bdd\uff0c\u5c31\u5c06\u5176\u52a0\u5165\u5230p.children\u4e2d\uff0c\u770b\u5230\u8fd9\u91cc\u7684 map\u662f\u4e2acanceler\uff0c\u53ef\u4ee5\u63a5\u6536\u4efb\u4f55\u5b9e\u73b0\u53d6\u6d88\u5668 \u7684\u7c7b\u578b\u3002\u8fd9\u91cc\u4e3a\u4f55\u8981\u52a0\u9501\u5462\uff1f\u56e0\u4e3a\u8981\u5bf9p.err\u4ee5\u53cap.children\u8fdb\u884c\u8bfb\u53d6\u4e0e\u5199\u5165\u64cd\u4f5c\uff0c\u8981\u786e\u4fdd\u534f\u7a0b\u5b89\u5168\u6240\u4ee5\u624d\u52a0\u7684\u9501\u3002<\/li>\n<\/ul>\n<ul>\n<li>\u5982\u679c\u4e0d\u662f*cancelCtx\u7c7b\u578b\u5c31\u8bf4\u660eparent\u662f\u4e2a\u88ab\u5c01\u88c5\u7684\u5176\u4ed6\u5b9e\u73b0 Context \u63a5\u53e3\u7684\u7c7b\u578b\uff0c\u5219\u4f1a\u5c06goroutines\u662f\u4e2aint\u52a01\u8fd9\u662f\u4e3a\u4e86\u6d4b\u8bd5\u4f7f\u7528\u7684\uff0c\u53ef\u4ee5\u4e0d\u7ba1\u5b83\u3002\u5e76\u4e14\u4f1a\u542f\u52a8\u4e2a\u534f\u7a0b\uff0c\u76d1\u542c\u7236Context \uff0c\u5982\u679c\u7236Context\u88ab\u53d6\u6d88\uff0c\u5219\u53d6\u6d88\u5b50Context\uff0c\u5982\u679c\u76d1\u542c\u5230\u5b50Context\u5df2\u7ecf\u7ed3\u675f\uff08\u53ef\u80fd\u662f\u4e0a\u5c42\u4e3b\u52a8\u8c03\u7528CancelFunc\uff09\u5219\u5c31\u5565\u4e5f\u4e0d\u7528\u505a\u4e86\u3002<\/li>\n<\/ul>\n<pre><code>if p, ok := parentCancelCtx(parent); ok {\n\u00a0\u00a0\u00a0\u00a0p.mu.Lock()\n\u00a0\u00a0\u00a0\u00a0if p.err != nil {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ parent has already been canceled\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0child.cancel(false, p.err)\n\u00a0\u00a0\u00a0\u00a0} else {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if p.children == nil {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0p.children = make(map[canceler]struct{})\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0p.children[child] = struct{}{}\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0p.mu.Unlock()\n\u00a0\u00a0} else {\n\u00a0\u00a0\u00a0\u00a0atomic.AddInt32(&amp;goroutines, +1)\n\u00a0\u00a0\u00a0\u00a0go func() {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0select {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case &lt;-parent.Done():\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0child.cancel(false, parent.Err())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0case &lt;-child.Done():\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}()\n\u00a0\u00a0}<\/code><\/pre>\n<p>\u63a5\u4e0b\u6765\u770b\u770bparentCancelCtx\u7684\u5b9e\u73b0\uff1a\u5b83\u662f\u4e3a\u4e86\u627e\u5bfbparent\u5e95\u4e0b\u7684 *cancelCtx\uff0c<\/p>\n<p>\u5b83\u9996\u5148\u68c0\u67e5parent.Done\uff08\uff09\u5982\u679c\u662f\u4e00\u4e2aclosedchan\u8fd9\u4e2a\u9891\u9053 \u5728\u521d\u59cb\u5316\u65f6\u5df2\u7ecf\u662f\u4e2a\u4e00\u4e2a\u88ab\u5173\u95ed\u7684\u901a\u9053\u6216\u8005\u672anil\u7684\u8bdd\uff08emptyCtx\uff09\u90a3\u5c31\u76f4\u63a5\u8fd4\u56de nil\uff0cfalse\u3002<\/p>\n<pre><code>func parentCancelCtx(parent Context) (*cancelCtx, bool) {\n\u00a0\u00a0done := parent.Done()\n\u00a0\u00a0if done == closedchan || done == nil {\n\u00a0\u00a0\u00a0\u00a0return nil, false\n}<\/code><\/pre>\n<pre><code>var closedchan = make(chan struct{})\nfunc init() {\n\u00a0\u00a0close(closedchan)<\/code><\/pre>\n<pre><code>p, ok := parent.Value(&amp;cancelCtxKey).(*cancelCtx)\nif !ok {\n\u00a0\u00a0return nil, false\n}<\/code><\/pre>\n<p>\u63a5\u7740\u5224\u65ad\u662f\u5426parent\u662f*cancelCtx\u7c7b\u578b\uff0c\u5982\u679c\u4e0d\u662f\u5219\u8fd4\u56denil\uff0cfalse\uff0c\u8fd9\u91cc\u8c03\u7528\u4e86parent.Value\u65b9\u6cd5\uff0c\u5e76\u6700\u7ec8\u53ef\u80fd\u4f1a\u843d\u5230value\u65b9\u6cd5\uff1a<\/p>\n<pre><code>func value(c Context, key any) any {\n\u00a0\u00a0for {\n\u00a0\u00a0\u00a0\u00a0switch ctx := c.(type) {\n\u00a0\u00a0\u00a0\u00a0case *valueCtx:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if key == ctx.key {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return ctx.val\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0c = ctx.Context\n\u00a0\u00a0\u00a0\u00a0case *cancelCtx:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if key == &amp;cancelCtxKey {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return c\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0c = ctx.Context\n\u00a0\u00a0\u00a0\u00a0case *timerCtx:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if key == &amp;cancelCtxKey {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return &amp;ctx.cancelCtx\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0c = ctx.Context\n\u00a0\u00a0\u00a0\u00a0case *emptyCtx:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return nil\n\u00a0\u00a0\u00a0\u00a0default:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return c.Value(key)\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0}\n}<\/code><\/pre>\n<ul>\n<li>\u5982\u679c\u662f*valueCtx\uff0c\u5e76\u4e14key==ctx.key\u5219\u8fd4\u56de\uff0c\u5426\u5219\u4f1a\u5c06c\u8d4b\u503c\u4e3a ctx.Context\uff0c\u7ee7\u7eed\u4e0b\u4e00\u4e2a\u5faa\u73af<\/li>\n<li>\u5982\u679c\u662f*cancelCtx\u5e76\u4e14key==&#038;cancelCtxKey\u5219\u8bf4\u660e\u627e\u5230\u4e86\uff0c\u76f4\u63a5\u8fd4\u56de\uff0c\u5426\u5219c= ctx.\u4e0a\u4e0b\u6587\u7ee7\u7eed<\/li>\n<li>\u5982\u679c\u662f<em>timerCtx\uff0c\u5e76\u4e14key== &#038;cancelCtxKey\u5219\u4f1a\u8fd4\u56de\u5185\u90e8\u7684<\/em>cancelCtx<\/li>\n<li>\u5982\u679c\u662f*emptyCtx \u5219\u76f4\u63a5\u8fd4\u56denil\uff0c<\/li>\n<li>\u9ed8\u8ba4\u5373\u5982\u679c\u662f\u7528\u6237\u81ea\u5b9a\u4e49\u5b9e\u73b0\u5219\u8c03\u7528\u5bf9\u5e94\u7684Value\u627e\u5bfb<\/li>\n<\/ul>\n<p>\u53ef\u4ee5\u53d1\u73b0\u5982\u679c\u5d4c\u5957\u5b9e\u73b0\u8fc7\u591a\u7684\u8bdd\u8fd9\u4e2a\u65b9\u6cd5\u5176\u5b9e\u662f\u4e00\u4e2a\u9012\u5f52\u8c03\u7528\u3002<\/p>\n<p>\u5982\u679c\u662f\u5219\u8981\u7ee7\u7eed\u5224\u65adp.done\u4e0eparent.Done\uff08\uff09\u662f\u5426\u76f8\u7b49\uff0c\u5982\u679c\u6ca1\u6709\u5219\u8bf4\u660e\uff1a*cancelCtx\u5df2\u7ecf\u88ab\u5305\u88c5\u5728\u4e00\u4e2a\u81ea\u5b9a\u4e49\u5b9e\u73b0\u4e2d\uff0c\u63d0\u4f9b\u4e86\u4e00\u4e2a\u4e0d\u540c\u7684\u5305\u88c5\uff0c\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\u5c31\u8fd4\u56denil\uff0cfalse\uff1a<\/p>\n<pre><code>pdone, _ := p.done.Load().(chan struct{})\nif pdone != done {\n\u00a0\u00a0return nil, false\n}\nreturn p, true<\/code><\/pre>\n<p>\u6784\u9020\u7b97\u662f\u7ed3\u675f\u4e86\uff0c\u63a5\u4e0b\u6765\u770b\u770b\u5982\u4f55\u53d6\u6d88\u7684\uff1a<\/p>\n<ul>\n<li>\u68c0\u67e5err\u662f\u5426\u4e3anil<\/li>\n<\/ul>\n<pre><code> if err == nil {\n\u00a0\u00a0\u00a0\u00a0panic(&quot;context: internal error: missing cancel error&quot;)\n\u00a0\u00a0} <\/code><\/pre>\n<ul>\n<li>\u7531\u4e8e\u8981\u5bf9err\u3001cancelCtx.done\u4ee5\u53cachildren\u8fdb\u884c\u64cd\u4f5c\uff0c\u6240\u4ee5\u8981\u52a0\u9501<\/li>\n<li>\u5982\u679cc.err\u4e0d\u4e3anil\u5219\u8bf4\u660e\u5df2\u7ecf\u53d6\u6d88\u8fc7\u4e86\uff0c\u76f4\u63a5\u8fd4\u56de\u3002\u5426\u5219\u5c06c.err=err\u8d4b\u503c\uff0c\u8fd9\u91cc\u770b\u5230\u53ea\u6709\u7b2c\u4e00\u6b21\u8c03\u7528\u624d\u4f1a\u8d4b\u503c\uff0c\u591a\u6b21\u8c03\u7528\u7531\u4e8e\u5df2\u7ecf\u6709 \uff01= nil+\u9501\u7684\u68c0\u67e5\uff0c\u6240\u4ee5\u4f1a\u76f4\u63a5\u8fd4\u56de\uff0c\u4e0d\u4f1a\u91cd\u590d\u8d4b\u503c<\/li>\n<\/ul>\n<pre><code>c.mu.Lock()\n\u00a0\u00a0if c.err != nil {\n\u00a0\u00a0\u00a0\u00a0c.mu.Unlock()\n\u00a0\u00a0\u00a0\u00a0return \/\/ already canceled\n\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0c.err = err<\/code><\/pre>\n<ul>\n<li>\u4f1a\u5c1d\u8bd5\u4ecec.done\u83b7\u53d6\uff0c\u5982\u679c\u4e3anil\uff0c\u5219\u4fdd\u5b58\u4e00\u4e2aclosedchan\uff0c\u5426\u5219\u5c31\u5173\u95edd\uff0c\u8fd9\u6837\u5f53\u4f60context.Done\uff08\uff09\u65b9\u6cd5\u8fd4\u56de\u7684channel\u624d\u4f1a\u8fd4\u56de\u3002<\/li>\n<\/ul>\n<pre><code>d, _ := c.done.Load().(chan struct{})\n\n\u00a0\u00a0if d == nil {\n\n\u00a0\u00a0\u00a0\u00a0c.done.Store(closedchan)\n\n\u00a0\u00a0} else {\n\n\u00a0\u00a0\u00a0\u00a0close(d)\n\n\u00a0\u00a0}<\/code><\/pre>\n<ul>\n<li>\u5faa\u73af\u904d\u5386c.children\u53bb\u5173\u95ed\u5b50Context\uff0c\u53ef\u4ee5\u770b\u5230\u91ca\u653e\u5b50context\u65f6\u4f1a\u83b7\u53d6 \u5b50Context\u7684\u9501\uff0c\u540c\u65f6\u4e5f\u4f1a\u83b7\u53d6\u7236Context\u7684\u9501\u3002\u6240\u4ee5\u624d\u662f\u7ebf\u7a0b\u5b89\u5168\u7684\u3002\u7ed3\u675f\u540e\u91ca\u653e\u9501<\/li>\n<\/ul>\n<pre><code>     d, _ := c.done.Load().(chan struct{})\n\n\u00a0\u00a0if d == nil {\n\n\u00a0\u00a0\u00a0\u00a0c.done.Store(closedchan)\n\n\u00a0\u00a0} else {\n\n\u00a0\u00a0\u00a0\u00a0close(d)\n\n\u00a0\u00a0}<\/code><\/pre>\n<ul>\n<li>\u5982\u679c\u8981\u5c06\u5176\u4ece\u7236Context\u5220\u9664\u4e3atrue\uff0c\u5219\u5c06\u5176\u4ece\u7236\u4e0a\u4e0b\u6587\u5220\u9664<\/li>\n<\/ul>\n<pre><code>if removeFromParent {\n\n\u00a0\u00a0\u00a0\u00a0removeChild(c.Context, c)\n\n\u00a0\u00a0}<\/code><\/pre>\n<p>removeChild\u4e5f\u6bd4\u8f83\u7b80\u5355\uff0c\u5f53\u4e3a*cancelCtx\u5c31\u5c06\u5176\u4eceChildren\u5185\u5220\u9664\uff0c\u4e3a\u4e86\u4fdd\u8bc1\u7ebf\u7a0b\u5b89\u5168\u4e5f\u662f\u52a0\u9501\u7684\u3002<\/p>\n<pre><code>func removeChild(parent Context, child canceler) {\n\n\u00a0\u00a0p, ok := parentCancelCtx(parent)\n\n\u00a0\u00a0if !ok {\n\n\u00a0\u00a0\u00a0\u00a0return\n\n\u00a0\u00a0}\n\n\u00a0\u00a0p.mu.Lock()\n\n\u00a0\u00a0if p.children != nil {\n\n\u00a0\u00a0\u00a0\u00a0delete(p.children, child)\n\n\u00a0\u00a0}\n\n\u00a0\u00a0p.mu.Unlock()\n\n}<\/code><\/pre>\n<p>Done\u5c31\u662f\u8fd4\u56de\u4e00\u4e2achannel\u7528\u4e8e\u544a\u77e5\u5e94\u7528\u7a0b\u5e8f\u4efb\u52a1\u5df2\u7ecf\u7ec8\u6b62\uff1a\u8fd9\u4e00\u6b65\u662f\u53ea\u8bfb\u6ca1\u6709\u52a0\u9501\uff0c\u5982\u679c\u6ca1\u6709\u8bfb\u53d6\u5230\u5219\u5c1d\u8bd5\u52a0\u9501\uff0c\u518d\u8bfb\u4e00\u6b21\uff0c\u8fd8\u6ca1\u8bfb\u5230\u5219\u521b\u5efa\u4e00\u4e2achan\uff0c\u53ef\u4ee5\u770b\u5230\u8fd9\u662f\u4e00\u4e2a\u61d2\u521b\u5efa\u7684\u8fc7\u7a0b\u3002\u6240\u4ee5\u5f53\u7528\u6237\u4e3b\u52a8\u8c03\u7528CancelFunc\u65f6\uff0c\u5176\u5b9e\u6839\u672c\u5c31\u662f\u5c06c.done\u5185\u5b58\u50a8\u7684chan close\u6389\uff0c\u8fd9\u5176\u4e2d\u53ef\u80fd\u7275\u626f\u5230\u7236\u5173\u95ed\uff0c\u4e5f\u8981\u5faa\u73af\u5173\u95ed\u5b50Context\u8fc7\u7a0b\u3002<\/p>\n<pre><code>func (c *cancelCtx) Done() &lt;-chan struct{} {\n\n\u00a0\u00a0d := c.done.Load()\n\n\u00a0\u00a0if d != nil {\n\n\u00a0\u00a0\u00a0\u00a0return d.(chan struct{})\n\n\u00a0\u00a0}\n\n\u00a0\u00a0c.mu.Lock()\n\n\u00a0\u00a0defer c.mu.Unlock()\n\n\u00a0\u00a0d = c.done.Load()\n\n\u00a0\u00a0if d == nil {\n\n\u00a0\u00a0\u00a0\u00a0d = make(chan struct{})\n\n\u00a0\u00a0\u00a0\u00a0c.done.Store(d)\n\n\u00a0\u00a0}\n\n\u00a0\u00a0return d.(chan struct{})\n\n}<\/code><\/pre>\n<p>cancelCtx\u4e3b\u8981\u5185\u5bb9\u5c31\u8fd9\u4e48\u591a\uff0c\u63a5\u4e0b\u91cc\u5c31\u662ftimerCtx\u4e86<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042547171\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2>\u8ba1\u65f6\u5668<\/h2>\n<p>\u56de\u987e\u4e0btimerCtx\u5b9a\u4e49\uff0c\u5c31\u662f\u5185\u5d4c\u4e86\u4e00\u4e2acancelCtx\u53e6\u5916\u591a\u4e86\u4e24\u4e2a\u5b57\u6bb5timer\u548cdeadline\uff0c\u8fd9\u4e5f\u662f\u7ec4\u5408\u7684\u4f53\u73b0\u3002<\/p>\n<pre><code>type timerCtx struct {\n\n\u00a0\u00a0cancelCtx\n\n\u00a0\u00a0timer *time.Timer \/\/ Under cancelCtx.mu.\n\n\u00a0\n\n\u00a0\u00a0deadline time.Time\n\n}<\/code><\/pre>\n<p>\u4e0b\u9762\u5c31\u770b\u770b\u4e24\u4e2a\u6784\u9020\u51fd\u6570\uff0cWithDeadline\u4e0eWithTimeout\uff0cWithTimeout\u5c31\u662f\u5bf9WithDealine\u7684\u4e00\u5c42\u7b80\u5355\u5c01\u88c5\u3002<\/p>\n<p>\u68c0\u67e5\u4e0d\u591a\u8bf4\u4e86\uff0c \u7b2c\u4e8c\u4e2a\u68c0\u67e5\u5982\u679c\u7236context\u7684\u622a\u6b62\u65f6\u95f4\u6bd4\u4f20\u9012\u8fdb\u6765\u7684\u65e9\u7684\u8bdd\uff0c\u8fd9\u4e2a\u65f6\u95f4\u5c31\u65e0\u7528\u4e86\uff0c\u90a3\u4e48\u5c31\u9000\u5316\u6210cancelCtx\u4e86\u3002<\/p>\n<pre><code>func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {\n\n\u00a0\u00a0if parent == nil {\n\n\u00a0\u00a0\u00a0\u00a0panic(&quot;cannot create context from nil parent&quot;)\n\n\u00a0\u00a0}\n\n\u00a0\u00a0if cur, ok := parent.Deadline(); ok &amp;&amp; cur.Before(d) {\n\n\u00a0\u00a0\u00a0\u00a0return WithCancel(parent)\n\n\u00a0\u00a0}<\/code><\/pre>\n<pre><code>func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {\n\n\u00a0\u00a0return WithDeadline(parent, time.Now().Add(timeout))\n\n}<\/code><\/pre>\n<p>\u6784\u9020timerCtx\u5e76\u8c03\u7528propagateCancel\uff0c\u8fd9\u4e2a\u5df2\u7ecf\u5728\u4e0a\u9762\u4ecb\u7ecd\u8fc7\u4e86\u3002<\/p>\n<pre><code>c := &amp;timerCtx{\n\n\u00a0\u00a0\u00a0\u00a0cancelCtx: newCancelCtx(parent),\n\n\u00a0\u00a0\u00a0\u00a0deadline: \u00a0d,\n\n\u00a0\u00a0}\n\n\u00a0\u00a0propagateCancel(parent, c)<\/code><\/pre>\n<p>\u63a5\u7740\u4f1a\u770b\uff0c\u4f1a\u5148\u5229\u7528time.\u76f4\u5230\uff08d.\u5206\u65f6\u3002Now\uff08\uff09\uff09 \u6765\u5224\u65ad\u4f20\u5165\u7684 deadlineTime\u4e0e\u5f53\u524d\u65f6\u95f4\u5dee\u503c\uff0c\u5982\u679c\u5728\u5f53\u524d\u65f6\u95f4\u4e4b\u524d\u7684\u8bdd\u8bf4\u660e\u5df2\u7ecf\u8be5\u53d6\u6d88\u4e86\uff0c\u6240\u4ee5\u4f1a\u76f4\u63a5\u8c03\u7528cancel\u51fd\u6570\u8fdb\u884c\u53d6\u6d88\uff0c\u5e76\u4e14\u5c06\u5176\u4ece\u7236Context\u4e2d\u5220\u9664\u3002\u5426\u5219\u5c31\u521b\u5efa\u4e00\u4e2a\u5b9a\u65f6\u5668\uff0c\u5f53\u65f6\u95f4\u5230\u8fbe\u4f1a\u8c03\u7528\u53d6\u6d88\u51fd\u6570\uff0c\u8fd9\u91cc\u662f\u5b9a\u65f6\u8c03\u7528\uff0c\u4e5f\u53ef\u80fd\u7528\u6237\u4e3b\u52a8\u8c03\u7528\u3002<\/p>\n<pre><code>dur := time.Until(d)\n\n\u00a0\u00a0if dur &lt;= 0 {\n\n\u00a0\u00a0\u00a0\u00a0c.cancel(true, DeadlineExceeded)\n\n\u00a0\u00a0\u00a0\u00a0return c, func() { c.cancel(false, Canceled) }\n\n\u00a0\u00a0}\n\n\u00a0\u00a0c.mu.Lock()\n\n\u00a0\u00a0defer c.mu.Unlock()\n\n\u00a0\u00a0if c.err == nil {\n\n\u00a0\u00a0\u00a0\u00a0c.timer = time.AfterFunc(dur, func() {\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0c.cancel(true, DeadlineExceeded)\n\n\u00a0\u00a0\u00a0\u00a0})\n\n\u00a0\u00a0}\n\n\u00a0\u00a0return c, func() { c.cancel(true, Canceled) }<\/code><\/pre>\n<p>\u4e0b\u9762\u770b\u770bcancel\u5b9e\u73b0\u5427\uff0c\u76f8\u6bd4\u8f83cancelCtx\u5c31\u6bd4\u8f83\u7b80\u5355\u4e86\uff0c\u5148\u53d6\u6d88 cancelCtx\uff0c\u4e5f\u8981\u52a0\u9501\uff0c\u5c06c.timer\u505c\u6b62\u5e76\u8d4b\u503cnil\uff0c\u8fd9\u91cc\u4e5f\u662f\u7b2c\u4e00\u6b21\u8c03\u7528\u624d\u4f1a\u8d4b\u503cnil\uff0c\u56e0\u4e3a\u5916\u5c42\u8fd8\u6709\u4e2ac.timer \uff01=nil\u7684\u5224\u65ad\uff0c\u6240\u4ee5\u591a\u6b21\u8c03\u7528\u53ea\u6709\u4e00\u6b21\u8d4b\u503c\u3002<\/p>\n<pre><code>func (c *timerCtx) cancel(removeFromParent bool, err error) {\n\n\u00a0\u00a0c.cancelCtx.cancel(false, err)\n\n\u00a0\u00a0if removeFromParent {\n\n\u00a0\u00a0\u00a0\u00a0\/\/ Remove this timerCtx from its parent cancelCtx's children.\n\n\u00a0\u00a0\u00a0\u00a0removeChild(c.cancelCtx.Context, c)\n\n\u00a0\u00a0}\n\n\u00a0\u00a0c.mu.Lock()\n\n\u00a0\u00a0if c.timer != nil {\n\n\u00a0\u00a0\u00a0\u00a0c.timer.Stop()\n\n\u00a0\u00a0\u00a0\u00a0c.timer = nil\n\n\u00a0\u00a0}\n\n\u00a0\u00a0c.mu.Unlock()\n\n}<\/code><\/pre>\n<p>\u76f8\u6bd4\u8f83\u4e8ecancelCtx\u8fd8\u8986\u76d6\u5b9e\u73b0\u4e86\u4e00\u4e2aDeadline\uff08\uff09\uff0c\u5c31\u662f\u8fd4\u56de\u5f53\u524d Context\u7684\u7ec8\u6b62\u65f6\u95f4\u3002<\/p>\n<pre><code>func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {\n\n\u00a0\u00a0return c.deadline, true\n\n}<\/code><\/pre>\n<p>\u4e0b\u9762\u5c31\u5230\u4e86\u6700\u540e\u4e00\u4e2a\u5185\u7f6e\u7684valueCtx\u4e86\u3002<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042547172\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<h2>\u503c<\/h2>\n<p>\u7ed3\u6784\u5668\u5c31\u66f4\u52a0\u52a0\u5355\uff0c\u5c31\u591a\u4e86key\uff0cval<\/p>\n<pre><code>type valueCtx struct {\n\n\u00a0Context\n\n\u00a0key, val any\n\n}<\/code><\/pre>\n<p>\u4e5f\u5c31\u6709\u4e2aValue method\u4e0d\u540c\uff0c\u53ef\u4ee5\u770b\u5230\u5e95\u5c42\u4f7f\u7528\u7684\u5c31\u662f\u6211\u4eec\u4e0a\u9762\u4ecb\u7ecd\u7684value\u51fd\u6570\uff0c\u91cd\u590d\u590d\u7528<\/p>\n<pre><code>func (c *valueCtx) Value(key any) any {\n\n\u00a0\u00a0if c.key == key {\n\n\u00a0\u00a0\u00a0\u00a0return c.val\n\n\u00a0\u00a0}\n\n\u00a0\u00a0return value(c.Context, key)\n\n}<\/code><\/pre>\n<p>\u51e0\u4e2a\u4e3b\u8981\u7684\u8bb2\u89e3\u5b8c\u4e86\uff0c\u53ef\u4ee5\u770b\u5230\u4e0d\u5230600\u884c\u4ee3\u7801\uff0c\u5c31\u5b9e\u73b0\u4e86\u8fd9\u4e48\u591a\u529f\u80fd\uff0c\u5176\u4e2d\u8574\u542b\u4e86\u7ec4\u5408\u3001\u5c01\u88c5\u3001\u7ed3\u6784\u4f53\u5d4c\u5957\u63a5\u53e3\u7b49\u8bb8\u591a\u7406\u5ff5\uff0c\u503c\u5f97\u597d\u597d\u7422\u78e8\u3002\u4e0b\u9762\u6211\u4eec\u518d\u770b\u770b\u5176\u4e2d\u6709\u4e9b\u6709\u610f\u601d\u7684\u5730\u65b9\u3002\u6211\u4eec\u4e00\u822c\u6253\u5370\u5b57\u7b26\u4e32\u90fd\u662f\u4f7f\u7528 fmt \u5305\uff0c\u90a3\u4e48\u4e0d\u4f7f\u7528fmt\u5305\u8be5\u5982\u4f55\u6253\u5370\u5462\uff1fcontext\u5305\u91cc\u5c31\u6709\u76f8\u5e94\u5b9e\u73b0\uff0c\u4e5f\u5f88\u7b80\u5355\uff0c\u5c31\u662f switch case\u6765\u5224\u65adv\u7c7b\u578b\u5e76\u8fd4\u56de\uff0c\u5b83\u8fd9\u4e48\u505a\u7684\u539f\u56e0\u4e5f\u6709\u8bf4\uff1a<\/p>\n<p>\u201c\u56e0\u4e3a\u6211\u4eec\u4e0d\u5e0c\u671b\u4e0a\u4e0b\u6587\u4f9d\u8d56\u4e8eunicode\u8868\u201d\uff0c\u8fd9\u53e5\u8bdd\u6211\u8fd8\u6ca1\u7406\u89e3\uff0c\u6709\u77e5\u9053\u7684\u5c0f\u4f19\u4f34\u53ef\u4ee5\u5728\u5e95\u4e0b\u8bc4\u8bba\uff0c\u6216\u8005\u7b49\u6211\u6709\u65f6\u95f4\u770b\u770bfmt\u5305\u5b9e\u73b0\u3002<\/p>\n<pre><code>func stringify(v any) string {\n\n\u00a0\u00a0switch s := v.(type) {\n\n\u00a0\u00a0case stringer:\n\n\u00a0\u00a0\u00a0\u00a0return s.String()\n\n\u00a0\u00a0case string:\n\n\u00a0\u00a0\u00a0\u00a0return s\n\n\u00a0\u00a0}\n\n\u00a0\u00a0return &quot;&lt;not Stringer&gt;&quot;\n\n}\n\n\u00a0\n\nfunc (c *valueCtx) String() string {\n\n\u00a0\u00a0return contextName(c.Context) + &quot;.WithValue(type &quot; +\n\n\u00a0\u00a0\u00a0\u00a0reflectlite.TypeOf(c.key).String() +\n\n\u00a0\u00a0\u00a0\u00a0&quot;, val &quot; + stringify(c.val) + &quot;)&quot;\n\n}<\/code><\/pre>\n<h2>\u4f7f\u7528Context\u7684\u51e0\u4e2a\u539f\u5219<\/h2>\n<p>\u76f4\u63a5\u5728\u51fd\u6570\u53c2\u6570\u4f20\u9012\uff0c\u4e0d\u8981\u5728struct\u4f20\u9012\uff0c\u8981\u660e\u786e\u4f20\u9012\uff0c\u5e76\u4e14\u4f5c\u4e3a\u7b2c\u4e00\u4e2a\u53c2\u6570\uff0c\u56e0\u4e3a\u8fd9\u6837\u53ef\u4ee5\u7531\u8c03\u7528\u65b9\u6765\u4f20\u9012\u4e0d\u540c\u7684\u4e0a\u4e0b\u6587\u5728\u4e0d\u540c\u7684\u65b9\u6cd5\u4e0a\uff0c\u5982\u679c\u4f60\u5728 struct\u5185\u4f7f\u7528context\u5219\u4e00\u4e2a\u5b9e\u4f8b\u662f\u516c\u7528\u4e00\u4e2acontext\u4e5f\u5c31\u5bfc\u81f4\u4e86\u534f\u7a0b\u4e0d\u5b89\u5168\uff0c\u8fd9\u4e5f\u662f\u4e3a\u4f55net\u5305Request\u8981\u62f7\u8d1d\u4e00\u4e2a\u65b0\u7684Request WithRequest\uff08context go 1.7 \u624d\u88ab\u5f15\u5165\uff09\uff0cnet\u5305\u7275\u626f\u8fc7\u591a\uff0c\u8981\u505a\u5230\u517c\u5bb9\u624d\u5d4c\u5165\u5230 struct\u5185\u3002<\/p>\n<p>\u4e0d\u8981\u4f7f\u7528nil\u800c\u5f53\u4f60\u4e0d\u77e5\u9053\u4f7f\u7528\u4ec0\u4e48\u65f6\u5219\u4f7f\u7528TODO\uff0c\u5982\u679c\u4f60\u7528\u4e86nil\u5219\u4f1a panic\u3002\u907f\u514d\u5230\u5904\u5224\u65ad\u662f\u5426\u4e3anil\u3002<\/p>\n<p>WithValue\u4e0d\u5e94\u8be5\u4f20\u9012\u4e1a\u52a1\u4fe1\u606f\uff0c\u53ea\u5e94\u8be5\u4f20\u9012\u7c7b\u4f3crequest-id\u4e4b\u7c7b\u7684\u8bf7\u6c42\u4fe1\u606f\u3002<\/p>\n<p>\u65e0\u8bba\u7528\u54ea\u4e2a\u7c7b\u578b\u7684Context\uff0c\u5728\u6784\u5efa\u540e\uff0c\u4e00\u5b9a\u8981\u52a0\u4e0a\uff1adefer cancel\uff08\uff09\uff0c\u56e0\u4e3a\u8fd9\u4e2a\u51fd\u6570\u662f\u53ef\u4ee5\u591a\u6b21\u8c03\u7528\u7684\uff0c\u4f46\u662f\u5982\u679c\u6ca1\u6709\u8c03\u7528\u5219\u53ef\u80fd\u5bfc\u81f4Context\u6ca1\u6709\u88ab\u53d6\u6d88\u7ee7\u800c\u5176\u5173\u8054\u7684\u4e0a\u4e0b\u6587\u8d44\u6e90\u4e5f\u5f97\u4e0d\u5230\u91ca\u653e\u3002<\/p>\n<p>\u5728\u4f7f\u7528WithValue\u65f6\uff0c\u5305\u5e94\u8be5\u5c06\u952e\u5b9a\u4e49\u4e3a\u672a\u5bfc\u51fa\u7684\u7c7b\u578b\u4ee5\u907f\u514d\u53d1\u751f\u78b0\u649e\uff0c\u8fd9\u91cc\u8d34\u4e2a\u5b98\u7f51\u7684\u4f8b\u5b50\uff1a<\/p>\n<pre><code>\/\/ package user \u8fd9\u91cc\u4e3a\u4e86\u6f14\u793a\u76f4\u63a5\u5728 main \u5305\u5b9a\u4e49\n\n\/\/ User \u662f\u5b58\u50a8\u5728 Context \u503c\n\ntype User struct {\n\n\u00a0\u00a0Name string\n\n\u00a0\u00a0Age \u00a0int\n\n}\n\n\u00a0\n\n\/\/ key \u662f\u975e\u5bfc\u51fa\u7684\uff0c\u53ef\u4ee5\u9632\u6b62\u78b0\u649e\n\ntype key int\n\n\u00a0\n\n\/\/ userKey \u662f\u5b58\u50a8 User \u7c7b\u578b\u7684\u952e\u503c\uff0c\u4e5f\u662f\u975e\u5bfc\u51fa\u7684\u3002\n\nvar userKey key\n\n\u00a0\n\n\/\/ NewContext \u521b\u5efa\u4e00\u4e2a\u65b0\u7684 Context\uff0c\u643a\u5e26 *User\n\nfunc NewContext(ctx context.Context, u *User) context.Context {\n\n\u00a0\u00a0return context.WithValue(ctx, userKey, u)\n\n}\n\n\u00a0\n\n\/\/ FromContext \u8fd4\u56de\u5b58\u50a8\u5728 ctx \u4e2d\u7684 *User\n\nfunc FromContext(ctx context.Context) (*User, bool) {\n\n\u00a0\u00a0u, ok := ctx.Value(userKey).(*User)\n\n\u00a0\u00a0return u, ok\n\n}<\/code><\/pre>\n<p>\u90a3\u600e\u4e48\u80fd\u591f\u9632\u6b62\u78b0\u649e\u5462\uff1f\u53ef\u4ee5\u505a\u4e2a\u793a\u4f8b\uff1a\u770b\u6700\u540e\u8f93\u51fa\uff0c\u6211\u4eec\u5728\u7b2c\u4e00\u884c\u5c31\u7528 userKey\u7684\u503c0\uff0c\u5b58\u50a8\u4e86\u4e00\u4e2a\u503c\u201ca\u201d\u3002<\/p>\n<p>\u7136\u540e\u518d\u5229\u7528NewContext\u5b58\u50a8\u4e86&#038;User\uff0c\u5e95\u5c42\u5b9e\u9645\u7528\u7684\u662f context.WithValue\uff08ctx\uff0cuserKey\uff0cu\uff09<\/p>\n<p>\u8bfb\u53d6\u65f6\u7528\u7684\u662fFromContext\uff0c\u4e24\u6b21\u5b58\u50a8\u5373\u4f7f\u5e95\u5c42\u7684key\u503c\u90fd\u4e3a0\uff0c \u4f46\u662f\u4e92\u4e0d\u5f71\u54cd\uff0c\u8fd9\u662f\u4e3a\u4ec0\u4e48\u5462\uff1f<\/p>\n<p>\u8fd8\u8bb0\u5f97WithValue\u600e\u4e48\u5b9e\u73b0\u7684\u4e48\uff1f\u4f60\u6bcf\u8c03\u7528\u4e00\u6b21\u90fd\u4f1a\u5305\u4e00\u5c42\uff0c\u5e76\u4e14\u4e00\u5c42\u4e00\u5c42\u89e3\u6790\uff0c\u800c\u4e14\u5b83\u4f1a\u6bd4\u8f83c.key==key\uff0c\u8fd9\u91cc\u8bb0\u4f4fgo\u7684==\u6bd4\u8f83\u662f\u6bd4\u8f83\u503c\u548c\u7c7b\u578b\u7684\uff0c\u4e8c\u8005\u90fd\u76f8\u7b49\u624d\u4e3atrue\uff0c\u800c\u6211\u4eec\u4f7f\u7528type key int\u6240\u4ee5userKey\u4e0e0\u5e95\u5c42\u503c\u867d\u7136\u4e00\u6837\uff0c\u4f46\u662f\u7c7b\u578b\u5df2\u7ecf\u4e0d\u4e00\u6837\u4e86\uff08\u8fd9\u91cc\u5c31\u662fmain.userKey\u4e0e0\uff09\uff0c\u6240\u4ee5\u5916\u90e8\u65e0\u8bba\u5b9a\u4e49\u4f55\u79cd\u7c7b\u578b\u90fd\u65e0\u6cd5\u5f71\u54cd\u5305\u5185\u7684\u7c7b\u578b\u3002\u8fd9\u4e5f\u662f\u5bb9\u6613\u4ee4\u4eba\u8ff7\u60d1\u7684\u5730\u65b9<\/p>\n<pre><code>package main\nimport (\n\u00a0\u00a0&quot;context&quot;\n\u00a0\u00a0&quot;fmt&quot;\n)\n\nfunc main() {\n\u00a0\u00a0ctx := context.WithValue(context.Background(), , &quot;a&quot;)\n\u00a0\u00a0ctx = NewContext(ctx, &amp;User{})\n\u00a0\u00a0v, _ := FromContext(ctx)\n\u00a0\u00a0fmt.Println(ctx.Value(0), v) \/\/ Output: a, &amp;{ 0}\n}<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042547173\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<p>\u5982\u679c\u4f60\u662f\u817e\u8baf\u6280\u672f\u5185\u5bb9\u521b\u4f5c\u8005\uff0c\u817e\u8baf\u4e91\u5f00\u53d1\u8005\u793e\u533a\u8bda\u9080\u60a8\u52a0\u5165<a href=\"https:\/\/link.segmentfault.com\/?enc=zwqw5nMMf%2FiASIt88kTsOg%3D%3D.%2Buk3CrdDtudJDOpxJSe%2FiFY%2BGl7PPG5Nyz422EOVfA7eOCztYOrRrR5Rxn7nJn%2FYIJCvLfoTl2LrMzX2DT%2FMvQ%3D%3D\" rel=\"nofollow\">\u3010\u817e\u8baf\u4e91\u539f\u521b\u5206\u4eab\u8ba1\u5212\u3011\uff0c<\/a>\u9886\u53d6\u793c\u54c1\uff0c\u52a9\u529b\u804c\u7ea7\u664b\u5347\u3002<\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000042547164\">https:\/\/segmentfault.com\/a\/1190000042547164<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5bfc\u8bed\u00a0|\u00a0\u672c\u6587\u63a8\u9009\u81ea\u817e\u8baf\u4e91\u5f00\u53d1\u8005\u793e\u533a-\u3010\u6280\u601d\u5e7f\u76ca \u00b7 \u817e\u8baf\u6280\u672f\u4eba\u539f\u521b\u96c6\u3011\u4e13\u680f\u3002\u8be5\u4e13\u680f\u662f\u817e\u8baf\u4e91\u5f00\u53d1\u8005\u793e\u533a\u4e3a\u817e\u8baf\u6280 [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[],"tags":[],"class_list":["post-10006609","post","type-post","status-publish","format-standard","hentry"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006609","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10006609"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006609\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10006609"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10006609"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10006609"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}