Open dushaoshuai opened 1 year ago
装饰器模式使用装饰器(decorator)包装对象(concrete component),动态地修饰其行为。装饰器和被装饰对象实现相同的接口(Component),因此可以无限次地对被装饰对象进行修饰。
context 包使用了装饰器模式。
context
Context 是一个接口:
Context
type Context interface { Deadline() (deadline time.Time, ok bool) Done() <-chan struct{} Err() error Value(key any) any }
emptyCtx 实现了 Context,但它又好像什么也没做:
emptyCtx
type emptyCtx int func (*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 any) any { return nil }
Background() 和 TODO() 都返回 *emptyCtx:
Background()
TODO()
*emptyCtx
var ( background = new(emptyCtx) todo = new(emptyCtx) ) func Background() Context { return background } func TODO() Context { return todo }
emptyCtx 为其它的装饰器提供了一个实现 Context 的基础。
type cancelCtx struct { Context // ... }
cancelCtx 自己实现了 Value(key any) any、Done() <-chan struct{}、Err() error 三个方法,将 Deadline() (deadline time.Time, ok bool) 方法委托给嵌入的匿名字段 Context,因此它实现了 Context。
cancelCtx
Value(key any) any
Done() <-chan struct{}
Err() error
Deadline() (deadline time.Time, ok bool)
WithCancel() 和 WithCancelCause() 都返回 *cancelCtx:
WithCancel()
WithCancelCause()
*cancelCtx
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { c := withCancel(parent) return c, func() { c.cancel(true, Canceled, nil) } } func WithCancelCause(parent Context) (ctx Context, cancel CancelCauseFunc) { c := withCancel(parent) return c, func(cause error) { c.cancel(true, Canceled, cause) } }
type timerCtx struct { *cancelCtx // ... }
timerCtx 自己实现了 Deadline() (deadline time.Time, ok bool) 方法,将其它三个方法委托给嵌入的匿名字段 cancelCtx。
timerCtx
WithDeadline() 和 WithTimeout() 都返回 *timeCtx:
WithDeadline()
WithTimeout()
*timeCtx
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) { // ... c := &timerCtx{ cancelCtx: newCancelCtx(parent), deadline: d, } // ... return c, func() { c.cancel(true, Canceled, nil) } } func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { return WithDeadline(parent, time.Now().Add(timeout)) }
type valueCtx struct { Context key, val any }
valueCtx 自己实现了 Value(key any) any 方法,将其它方法委托给嵌入的匿名字段 Context。
valueCtx
WithValue() 返回 *valueCtx:
WithValue()
*valueCtx
func WithValue(parent Context, key, val any) Context { // ... return &valueCtx{parent, key, val} }
注意所有对一个 Context 进行装饰返回另一个 Context 的函数,返回的都是接口而不是具体的实现。
装饰器模式使用装饰器(decorator)包装对象(concrete component),动态地修饰其行为。装饰器和被装饰对象实现相同的接口(Component),因此可以无限次地对被装饰对象进行修饰。
Context
context
包使用了装饰器模式。Context
是一个接口:emptyCtx
emptyCtx
实现了Context
,但它又好像什么也没做:Background()
和TODO()
都返回*emptyCtx
:emptyCtx
为其它的装饰器提供了一个实现Context
的基础。cancelCtx
cancelCtx
自己实现了Value(key any) any
、Done() <-chan struct{}
、Err() error
三个方法,将Deadline() (deadline time.Time, ok bool)
方法委托给嵌入的匿名字段Context
,因此它实现了Context
。WithCancel()
和WithCancelCause()
都返回*cancelCtx
:timerCtx
timerCtx
自己实现了Deadline() (deadline time.Time, ok bool)
方法,将其它三个方法委托给嵌入的匿名字段cancelCtx
。WithDeadline()
和WithTimeout()
都返回*timeCtx
:valueCtx
valueCtx
自己实现了Value(key any) any
方法,将其它方法委托给嵌入的匿名字段Context
。WithValue()
返回*valueCtx
:return interface instead of concrete implementation
注意所有对一个
Context
进行装饰返回另一个Context
的函数,返回的都是接口而不是具体的实现。