设为首页 加入收藏

TOP

带小伙伴手写 golang context(七)
2019-05-23 14:33:29 】 浏览:363
Tags:小伙伴 手写 golang context
chan struct{}) } // cancelCtx 可被取消的 context type cancelCtx struct { Context mu sync.Mutex // 互斥锁保证 goroutine 安全 done chan struct{} // 慢创建, 首次取消才会被调用的开关 children map[canceler]struct{} // 首次 context 取消后待取消的 child context err error // 首次取消 context 保留的 error } func (c *cancelCtx) Done() (done <-chan struct{}) { c.mu.Lock() if c.done == nil { c.done = make(chan struct{}) } done = c.done c.mu.Unlock() return } func (c *cancelCtx) Err() (err error) { c.mu.Lock() err = c.err c.mu.Unlock() return } func (c *cancelCtx) String() string { return contextName(c) + ".WithCancel" } // newCancelCtx returns an initialized cancelCtx func newCancelCtx(parent Context) cancelCtx { return cancelCtx{Context: parent} }

(这里用 "reflect" 标准包来表述 "internal/reflectlite" 内部才能使用的 "reflect" 包)

timer.go

package context

import (
	"time"
)

// timerCtx 带计时器和截止日期的 cancelCtx
type timerCtx struct {
	cancelCtx

	timer    *time.Timer // 依赖 cancelCtx.mu
	deadline time.Time   // context 截止时间
}

func (c *timerCtx) Deadline() (time.Time, bool) {
	return c.deadline, true
}

func (c *timerCtx) String() string {
	return contextName(c.cancelCtx.Context) + ".WithDeadline(" + c.deadline.String() + " [" + time.Until(c.deadline).String() + "])"
}

value.go

package context

import "reflect"

// valueCtx 储存键值对 context
type valueCtx struct {
	Context

	key, val interface{}
}

func (c *valueCtx) Value(key interface{}) interface{} {
	if c.key == key {
		return c.val
	}
	return c.Context.Value(key)
}

// stringify tries a bit to stringify v, without using fmt, since we don't
// want context depending on the unicode tables. This is only used by *valueCtx.String()
func stringify(v interface{}) string {
	switch s := v.(type) {
	case stringer:
		return s.String()
	case string:
		return s
	}
	return "<not Stringer>"
}

func (c *valueCtx) String() string {
	return contextName(c.Context) + ".WithValue(type " + reflect.TypeOf(c.key).String() + ", val " + stringify(c.val) + ")"
}

with.go

package context

import (
	"reflect"
	"time"
)

// WithValue returns a copy of parent in which the value associated with key is val
func WithValue(parent Context, key, val interface{}) Context {
	if key == nil {
		panic("nil key")
	}

	// key 不具备可比性时候, 会引发运行时恐慌 panic
	if !reflect.TypeOf(key).Comparable() {
		panic("key is not comparable")
	}

	return &valueCtx{parent, key, val}
}

// parentCancelCtx 获取 parent CancelCtx
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
	for {
		switch c := parent.(type) {
		case *cancelCtx:
			return c, true
		case *timerCtx:
			return &c.cancelCtx, true
		case *valueCtx:
			parent = c.Context
		default:
			return nil, false
		}
	}
}

// removeChild removes a context from its parent
func removeChild(parent Context, child canceler) {
	p, ok := parentCancelCtx(parent)
	if !ok {
		return
	}

	p.mu.Lock()
	if p.children != nil {
		delete(p.children, child)
	}
	p.mu.Unlock()
}

// closedchan 可重复使用且已经关闭通道
var closedchan = make
首页 上一页 4 5 6 7 8 下一页 尾页 7/8/8
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇golang 变量定义 下一篇simple go web application & 二..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目