go context

context

1、子协程修改context,用指针,如下,否则修改失败

ctx := context.Background()
go func(ctx *context.Context) {
    *ctx = context.WithValue(*ctx, "test", 2)
}(&ctx) //传指针
time.Sleep(time.Second)
fmt.Println(ctx.Value("test"))

2、cancel后,自身和子ctx都cancel,父ctx不cancel

如下例,ctx1是ctx2之父,ctx2是ctx3之父

ctx1 := context.Background()
ctx2, cancel := context.WithCancel(ctx1)
ctx3 := context.WithValue(ctx2, "test", "test string")
cancel()
go func(ctx context.Context) {
    if ctx.Err() != nil {
        fmt.Println("ctx1 closed")
    } else {
        fmt.Println("ctx1 not closed")
    }
}(ctx1)
go func(ctx context.Context) {
    if ctx.Err() != nil {
        fmt.Println("ctx2 closed")
    } else {
        fmt.Println("ctx2 not closed")
    }
}(ctx2)
go func(ctx context.Context) {
    if ctx.Err() != nil {
        fmt.Println("ctx3 closed")
    } else {
        fmt.Println("ctx3 not closed")
    }
}(ctx3)
time.Sleep(time.Second * 2)
// Unordered output:
// ctx1 not closed
// ctx2 closed
// ctx3 closed

cancel源码:

func (c *cancelCtx) cancel(removeFromParent bool, err error) {
	if err == nil {
		panic("context: internal error: missing cancel error")
	}
	c.mu.Lock()
	if c.err != nil {
		c.mu.Unlock()
		return // already canceled
	}
	c.err = err
	if c.done == nil {
		c.done = closedchan
	} else {
		close(c.done)
	}
	for child := range c.children {
		// NOTE: acquiring the child's lock while holding parent's lock.
		child.cancel(false, err)
	}
	c.children = nil
	c.mu.Unlock()

	if removeFromParent {
		removeChild(c.Context, c)
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值