我的问题是关于Context
interface的设计选择。如果我想从child
创建parent
上下文,我可以执行以下操作:
child, cancel := context.WithTimeout(parent, timeout)
如果WithTimeout
是界面的一部分会不会更好,所以我们可以简单地写一下:
child, cancel := parent.WithTimeout(timeout)
对我来说似乎更清洁。它更短,不需要import context
。
为什么生成子上下文的函数不属于Context
接口?
答案 0 :(得分:6)
这是context.Context
类型:
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
很简单。如果你要编写它的实现,你能做到吗?是的,很容易。因为没有&#34; setter&#34;方法,每个方法只能返回一个默认值/ zero value,它是一个有效的&#34;实现。这正是背景和TODO背景所做的事情(context.Background()
和context.TODO()
)。
如果要添加从现有的派生新函数的函数(例如context.WithCancel()
,context.WithDeadline()
等)作为Context
接口的一部分本身,需要为所有人提供(有效)实施,这是不可行的;并且很少需要同时进行所有这些,因此浪费资源。
扩展程序负责添加实现。如果您查看context
包的实施方式:context/context.go
,您会看到不同的context.Context
实施不同的&#34;衍生品&#34;或&#34;扩展&#34;:
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// struct{}, since vars of this type must have distinct addresses.
type emptyCtx int
// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
Context
done chan struct{} // closed by the first cancel call.
mu sync.Mutex
children map[canceler]bool // set to nil by the first cancel call
err error // set to non-nil by the first cancel call
}
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
// implement Done and Err. It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel.
type timerCtx struct {
cancelCtx
timer *time.Timer // Under cancelCtx.mu.
deadline time.Time
}
// 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{}
}
显然,我们可以为不在context.Context
包中的context
组成其他有用的扩展程序。如果您有新想法,是否还要将其添加到Context
界面? 这会破坏所有现有的实施,因为显然你的新想法并未在其他实施中实现。目前的实施。
答案 1 :(得分:1)
这是因为WithContext
与parent
无关 - 例如父母不应该也不应该对你可以从中创建子上下文这一事实有任何想法。在Go ideology中,界面应该尽可能小。
它更具可读性和清晰度,您将获得什么作为输出。在当前的实施中,someVar, _ := context.WithTimeout(value)
被称为some variable is a new (:=) context with a timeout
。在您建议的版本中,它someVar, _ := parent.WithTimeout(value)
有点模糊。