当前位置: 首页 > news >正文

golang context

作用:用于在go协程中 传递上下文、超时、取消、传值

底层实现:是由互斥锁、channel、map来实现的
互斥锁:保护临界资源
channel: 用于信号通知,比如ctx.Done()
map: 保存父ctx下派生的所有子ctx, 父ctx关闭,子ctx都关闭

实现的接口

type Context interface {Deadline() (deadline time.Time, ok bool)Done() <-chan struct{}Err() errorValue(key interface{}) interface{}
}

空ctx

type emptyCtx intfunc (*emptyCtx) Deadline() (deadline time.Time, ok bool) {return
}func (*emptyCtx) Done() <-chan struct{} {return nil
}func (*emptyCtx) Err() error {return nil
}func (*emptyCtx) Value(key interface{}) interface{} {return nil
}

cancel ctx

使用map保存所有子ctx,确保父ctx cancel后,子ctx也cancel

type cancelCtx struct {Contextmu       sync.Mutex            // protects following fieldsdone     chan struct{}         // created lazily, closed by first cancel callchildren map[canceler]struct{} // set to nil by the first cancel callerr      error                 // set to non-nil by the first cancel call
}func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {if parent == nil {panic("cannot create context from nil parent")}c := newCancelCtx(parent)propagateCancel(parent, &c)return &c, func() { c.cancel(true, Canceled) }
}// newCancelCtx returns an initialized cancelCtx.
func newCancelCtx(parent Context) cancelCtx {return cancelCtx{Context: parent}
}func propagateCancel(parent Context, child canceler) {fmt.Println("propagateCancel")done := parent.Done()if done == nil {return // parent is never canceled}select {case <-done:// parent is already canceledchild.cancel(false, parent.Err())returndefault:}if p, ok := parentCancelCtx(parent); ok {p.mu.Lock()if p.err != nil {// parent has already been canceledchild.cancel(false, p.err)} else {if p.children == nil {p.children = make(map[canceler]struct{})}// 保存子ctxp.children[child] = struct{}{}}p.mu.Unlock()} else {atomic.AddInt32(&goroutines, +1)go func() {select {case <-parent.Done():child.cancel(false, parent.Err())case <-child.Done():}}()}
}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 = errif c.done == nil {c.done = closedchan} else {close(c.done) // 关闭channel, 用于通知ctx.Done()}// 关闭所有子ctxfor child := range c.children {// NOTE: acquiring the child's lock while holding parent's lock.child.cancel(false, err)}c.children = nilc.mu.Unlock()if removeFromParent {removeChild(c.Context, c)}
}

timeout ctx

在cancelctx的基础上实现,只是多了个定时器自动调用cancel

type timerCtx struct {cancelCtxtimer *time.Timer // Under cancelCtx.mu.deadline time.Time
}func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {if parent == nil {panic("cannot create context from nil parent")}if cur, ok := parent.Deadline(); ok && cur.Before(d) {// The current deadline is already sooner than the new one.return WithCancel(parent)}c := &timerCtx{cancelCtx: newCancelCtx(parent),deadline:  d,}propagateCancel(parent, c)dur := time.Until(d)if dur <= 0 {c.cancel(true, DeadlineExceeded) // deadline has already passedreturn c, func() { c.cancel(false, Canceled) }}c.mu.Lock()defer c.mu.Unlock()if c.err == nil {c.timer = time.AfterFunc(dur, func() {c.cancel(true, DeadlineExceeded)})}return c, func() { c.cancel(true, Canceled) }
}

value ctx

type valueCtx struct {Contextkey, val interface{}
}
func WithValue(parent Context, key, val interface{}) Context {if parent == nil {panic("cannot create context from nil parent")}if key == nil {panic("nil key")}//	if !reflectlite.TypeOf(key).Comparable() {//	panic("key is not comparable")//}return &valueCtx{parent, key, val}
}
func (c *valueCtx) Value(key interface{}) interface{} {if c.key == key {return c.val}return c.Context.Value(key)
}
http://www.lryc.cn/news/336656.html

相关文章:

  • GPT中的Transformer架构以及Transformer 中的注意力机制
  • Hive的简单学习二
  • Qt事件处理机制3-事件函数的分发
  • 4月9号总结
  • Linux生态系统:探索Linux的开源世界
  • XILINX 10G PCS PMA IP核使用
  • Scrapy框架内存泄漏问题及解决
  • app 创建快捷入口 在手机上面多个icon
  • 【网安小白成长之路】6.pkachu、sql-lbas、upload-lbas靶场搭建
  • vue 项目中添加DES加密
  • 【记录问题】如何测试虚拟机已经可以连接网络
  • MySQL数据库的详解(1)
  • Python 网络爬虫技巧分享:优化 Selenium 滚动加载网易新闻策略
  • Apache SeaTunnel 社区 3 月月报
  • ElasticSearch 的 ConstantScoreQuery 的理解
  • 【RV1106的ISP使用记录之一】基础环境搭建
  • mars3d.MaterialType.Image2修改配置面状:图片2的speed数值实现动画效果说明
  • Elasticsearch部署安装
  • Android零基础入门(一)配置环境和安装Android Studio
  • Golang编译优化——消除Copy指令
  • Java IO流对象流实操
  • Mapbox教程:一个简单Demo
  • 看AI赋能数智化 | Gooxi AI服务器闪耀CITE 2024
  • 大话设计模式——21.中介者模式(Mediator Pattern)
  • Linux 计算机网络
  • bash脚本中‘-b -u -p’‘$# -eq’‘#!/bin/bash’‘sed -i “s/\r//“ $1’的用法说明
  • 【人工智能】Gitee AI 天数智芯有奖体验开源AI模型,一定能有所收货,快来体验吧
  • Ceph学习 -8.认证管理-用户基础
  • 大创项目推荐 深度学习+opencv+python实现昆虫识别 -图像识别 昆虫识别
  • Python小工具提升工作效率【附完整版,可下载word】