type emptyCtx intfunc(*emptyCtx) Deadline() (deadline time.Time, ok bool) {
return
}
func(*emptyCtx) Done() <-chanstruct{} {
returnnil
}
func(*emptyCtx) Err() error {
returnnil
}
func(*emptyCtx) Value(key interface{}) interface{} {
returnnil
}
func(e *emptyCtx) String() string {
switch e {
case background:
return"context.Background"case todo:
return"context.TODO"
}
return"unknown empty Context"
}
var (
background = new(emptyCtx)
todo = new(emptyCtx)
)
funcBackground() Context {
return background
}
funcTODO() Context {
return todo
}
cancelCtx
// A cancelCtx can be canceled. When canceled, it also cancels any children// that implement canceler.type cancelCtx struct {
Context
mu sync.Mutex // protects following fields
done chanstruct{} // created lazily, closed by first cancel call
children map[canceler]struct{} // set to nil by the first cancel call
err error// set to non-nil by the first cancel call
}
func(c *cancelCtx) Done() <-chanstruct{} {
c.mu.Lock()
if c.done == nil {
c.done = make(chanstruct{})
}
d := c.done
c.mu.Unlock()
return d
}
func(c *cancelCtx) Err() error {
c.mu.Lock()
err := c.err
c.mu.Unlock()
return err
}
func(c *cancelCtx) String() string {
return fmt.Sprintf("%v.WithCancel", c.Context)
}
// cancel closes c.done, cancels each of c's children, and, if// removeFromParent is true, removes c from its parent's children.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)
}
}
package main
import (
"context""fmt""time"
)
functo1(ctx context.Context) {
n := 1for {
select {
case <-ctx.Done():
fmt.Println("to1 is over")
returndefault:
fmt.Println("to1 : ", n)
n++
time.Sleep(time.Second)
}
}
}
funcmain() {
// 设置为6秒后context结束
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second)
defer cancel()
go to1(ctx)
n := 1for {
select {
case <-time.Tick(2 * time.Second):
if n == 9 {
return
}
fmt.Println("number :", n)
n++
}
}
}
WithValue Context 基础上添加了 key : value 的键值对
context 形成的树状结构,后面的节点可以访问前面节点传导的数据
funcWithValue(parent Context, key, val interface{}) Context {
if key == nil {
panic("nil key")
}
if !reflect.TypeOf(key).Comparable() {
panic("key is not comparable")
}
return &valueCtx{parent, key, val}
}
// A valueCtx carries a key-value pair. It implements Value for that key and// delegates all other calls to the embedded Context.type valueCtx struct {
Context
key, val interface{}
}
使用示例 :
package main
import (
"context""fmt""time"
)
funcv3(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("v3 Done : ", ctx.Err())
returndefault:
fmt.Println(ctx.Value("key"))
time.Sleep(3 * time.Second)
}
}
}
funcv2(ctx context.Context) {
fmt.Println(ctx.Value("key"))
fmt.Println(ctx.Value("v1"))
// 相同键,值覆盖
ctx = context.WithValue(ctx, "key", "modify from v2")
go v3(ctx)
}
funcv1(ctx context.Context) {
if v := ctx.Value("key"); v != nil {
fmt.Println("key = ", v)
}
ctx = context.WithValue(ctx, "v1", "value of v1 func")
go v2(ctx)
for {
select {
default:
fmt.Println("print v1")
time.Sleep(time.Second * 2)
case <-ctx.Done():
fmt.Println("v1 Done : ", ctx.Err())
return
}
}
}
funcmain() {
ctx, cancel := context.WithCancel(context.Background())
// 向context中传递值
ctx = context.WithValue(ctx, "key", "main")
go v1(ctx)
time.Sleep(10 * time.Second)
cancel()
time.Sleep(3 * time.Second)
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?