我想WithContext為結構撰寫一個方法,并從net/http's 中汲取靈感Request.WithContext。
我的問題是:Request.WithContext如果背景關系為零,為什么會恐慌:
func (r *Request) WithContext(ctx context.Context) *Request {
if ctx == nil {
panic("nil context")
}
...
}
我的也應該這樣嗎?
有關為什么要創建WithContext方法的更多背景關系:我正在實作一個介面,該介面在其簽名中不提供背景關系引數,但相信實作需要它。
更具體地說,我正在撰寫一個 Redis 后端,用于gorilla/session使用Go的官方 Redis 客戶端,其中Get和Set方法采用context.Context.
這個想法是我的 redis 存盤將在需要時使用新的背景關系物件進行淺復制,然后使用:
type redisStore struct {
codecs []securecookie.Codec
backend Backend // custom interface for Redis client
options *sessions.Options
ctx context.Context
}
func (s *redisStore) WithContext(ctx context.Context) *redisStore {
if ctx == nil {
panic("nil context")
}
s2 := new(redisStore)
*s2 = *s
s2.ctx = ctx
return s2
}
// Backend
type Backend interface {
Set(context.Context, string, interface{}) error
Get(context.Context, string) (string, error)
Del(context.Context, string) error
}
uj5u.com熱心網友回復:
恐慌的目的是“快速失敗”并拒絕nil背景關系而不更改函式簽名。
如果函式沒有恐慌,那么它必須回傳錯誤以拒絕錯誤的輸入:
func (r *Request) WithContext(ctx context.Context) (*Request, error) {
if ctx == nil {
return nil, errors.New("nil ctx")
}
...
}
然后呼叫此函式的人必須處理錯誤以避免使用無效請求:
request, err = request.WithContext(nil)
if err != nil {
}
通過處理錯誤,您引入了一個控制流分支,并且您失去了方法鏈。您也不能立即將WithContext回傳值用于函式引數:
// cannot do, because WithContext returns an error too
data, err := fetchDataWithContext(request.WithContext(ctx), otherParam)
它還會創建一個最終會被垃圾收集的錯誤實體。這一切都很麻煩,可用性差和不必要的分配只是為了說“不要給我一個零背景關系”。
關于創建一個帶有背景關系的 redis 存盤,背景關系檔案很清楚:
包背景關系定義了背景關系型別,它在 API 邊界和行程之間攜帶截止日期、取消信號和其他請求范圍的值。
重要的細節是request-scoped。所以在redis客戶端本身設定背景關系與這個建議是相反的。您應該在每次 get/set 呼叫時傳遞背景關系值。
uj5u.com熱心網友回復:
如果客戶端關閉連接,則取消 HTTP 請求的背景關系。當背景關系被取消時,它的所有子背景關系也被取消,因此 nil 背景關系會導致恐慌。因此,您不能將 nil 背景關系傳遞給WithContext.
您的 redis 存盤是否應該恐慌取決于您將如何使用該背景關系。在結構中包含背景關系通常不是一個好主意。一種可以接受的方法是如果結構本身是一個背景關系。應該為每個呼叫創建背景關系,應該在呼叫期間一直存在,然后丟棄。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/358293.html
上一篇:通過介面訪問結構體欄位
