亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

我應該將 context.Context 傳遞給 Go 中的底層數據庫方法嗎?

我應該將 context.Context 傳遞給 Go 中的底層數據庫方法嗎?

Go
偶然的你 2023-01-03 15:47:58
我在這里使用半代碼只是為了展示我對代碼中發生的事情的意圖,而不是讓問題復雜化。我有一個main.go文件調用連接到 mongoDB 數據庫的方法:mStore := store.NewMongoStore()在NewMongoStore我有client.Connect用于連接數據庫的上下文中:ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)defer cancel()現在main.go我以這種方式將商店傳遞給我的路由器控制器文件:routes.GenericRoute(router, mStore)在GenericRoute我得到 mStore 并將其傳遞給函數處理程序時:func GenericRoute(router *gin.Engine, mStore store.Store) {    router.POST("/users", controllers.CreateUser(mStore))}現在CreateUser我再次創建一個上下文,如下所示,將文檔插入 MongoDB:ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)defer cancel()insertedId, err := repo.CreateUser(ctx, newUser{"John", "Doe"})在這里,我將上下文傳遞給以createUser插入一個新文檔。正如您在某些部分看到的,我已經通過了上下文,而在某些部分我沒有。我真的不知道我應該做什么?使用上下文的正確方法是什么?我應該始終傳遞上下文還是完全可以創建這樣的新上下文而不在方法參數中傳遞上下文。這種編碼的最佳實踐是什么?從性能的角度來看,哪個更好?
查看完整描述

2 回答

?
www說

TA貢獻1775條經驗 獲得超8個贊

根據我的經驗,Context有兩個主要用例:

  1. 傳遞信息。對于您的問題,您可能希望request_id為每個請求生成一個并將其傳遞到代碼的最低部分,并記錄它request_id以在整個代碼庫中進行錯誤跟蹤。

    1. 此功能并不總是有用,例如您想要初始化 MongoDB 連接,但它是在服務啟動期間完成的。此時沒有有意義的上下文,context.Background超時應該足夠了。

    2. 對從 中檢索到的變異值要小心,Context如果您要傳遞Context所有內容,這可能會導致并發訪問。

  2. 自動取消和超時。這兩個功能并非無中生有,您需要調整代碼以處理來自Context. 但是大多數帶有參數的第三方庫和標準庫Context都可以很好地處理這兩個特性(例如數據庫庫、HTTP 調用庫)。Context使用此功能,您可以在失效 后自動回收資源。

    1. 有時您會想要停止這種級聯行為,例如在后臺 goroutine 中寫入日志,那么您需要創建一個新的 goroutinecontext.Background()以避免這些寫入在上游上下文被取消后被取消。context.Background()還會清除信息上下文,因此有時您需要從上游上下文中提取上下文信息,并手動將它們附加到這個新上下文中。

Context將參數強制用于所有函數有點矯枉過正,(添加Context到簡單greatestCommonDivisor函數沒有意義)但是將Context參數添加到您需要的任何地方永遠不會造成傷害。Context具有足夠好的性能,對于您的用例(HTTP 服務器和數據庫編寫),它不應該對您的服務造成可見的開銷。


查看完整回答
反對 回復 2023-01-03
?
紫衣仙女

TA貢獻1839條經驗 獲得超15個贊

我對自己的問題找到了一個有趣的答案,所以如果有同樣的問題,我更愿意把它放在這里供未來的用戶使用。

如果我將連接到 Mongo 的 SAME 上下文傳遞給 touserController并將其進一步向下傳遞以CreateUser運行:

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)

注意:不是在函數中取消上下文,而是在NewMongoStore函數defer cancel()中取消上下文main。

10 秒后,如果你打電話POST /users,你會得到context deadline exceeded,所以基本上你不能使用這個上下文來做其他事情,你必須在每次CreateUser調用時創建新的上下文。

所以我寫的很好。在我的示例中,我等待 10 秒連接到mongo,插入操作上下文等待 1 秒。


查看完整回答
反對 回復 2023-01-03
  • 2 回答
  • 0 關注
  • 112 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號