日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
GoFrame如何優(yōu)雅的共享變量?Context的使用

前言

昨天merge代碼,發(fā)現(xiàn)了好多沖突,原因是同事在review項(xiàng)目,做鏈路追蹤,發(fā)現(xiàn)老項(xiàng)目有不少方法傳參不規(guī)范,沒(méi)有傳入Context,不方便做鏈路追蹤。

所以把這些方法和調(diào)用進(jìn)行了修改,導(dǎo)致了大量沖突,修復(fù)沖突又花了好長(zhǎng)時(shí)間

所以:傳參規(guī)范還是要在項(xiàng)目啟動(dòng)時(shí)就確定好呀,一定要搞清楚Context怎么用呀!

今天就為大家介紹一下Context的使用:

告訴大家Context是什么?怎么用?為什么要用Context以及使用中的小技巧和注意問(wèn)題。

Context是什么?

Context?指的是標(biāo)準(zhǔn)庫(kù)的context.Context?,是一個(gè)接口對(duì)象,常用于異步IO控制以及上下文流程變量的傳遞。

本文將要介紹的是Context如何優(yōu)雅的在業(yè)務(wù)流程中進(jìn)行變量的傳遞,以及為什么需要要進(jìn)行變量的傳遞。

為什么需要Context?

在Go?的執(zhí)行流程中,特別是HTTP/RPC?執(zhí)行流程中,沒(méi)有通過(guò)”全局變量”獲取請(qǐng)求參數(shù)的方式,只能通過(guò)上下文Context變量,傳遞到后續(xù)執(zhí)行流程的方法中。

如何使用?

Context上下文變量,包含了所有需要傳遞的共享變量。

并且Context中的共享變量是需要事先約定的,并且往往存儲(chǔ)為對(duì)象指針形式。

通過(guò)Context上下文,共享變量非常簡(jiǎn)單,下面通過(guò)示例帶大家了解一下如何傳遞和使用通用的共享變量。

一、結(jié)構(gòu)定義

上下文對(duì)象中往往存儲(chǔ)一些需要共享的變量,這些變量通常使用結(jié)構(gòu)化的對(duì)象來(lái)存儲(chǔ),以方便維護(hù)。

例如,我們?cè)趍odel定義一個(gè)上下文中的共享變量:

const (
// 上下文變量存儲(chǔ)鍵名,前后端系統(tǒng)共享
ContextKey = "ContextKey"
)

// 請(qǐng)求上下文結(jié)構(gòu)
type Context struct {
Session *ghttp.Session // 當(dāng)前Session管理對(duì)象
User *ContextUser // 上下文用戶信息
Data g.Map // 自定KV變量,業(yè)務(wù)模塊根據(jù)需要設(shè)置,不固定
}

// 請(qǐng)求上下文中的用戶信息
type ContextUser struct {
Id uint // 用戶ID
Passport string // 用戶賬號(hào)
Nickname string // 用戶名稱
Avatar string // 用戶頭像
}

介紹

  • model.ContextKey?常量表示存儲(chǔ)在context.Context?上下文變量中的鍵名,該鍵名用于從傳遞的context.Context變量中存儲(chǔ)/獲取業(yè)務(wù)自定義的共享變量。
  • model.Context?結(jié)構(gòu)體中的Session?表示當(dāng)前請(qǐng)求的Session?對(duì)象,在GoFrame?框架中每個(gè)HTTP?請(qǐng)求對(duì)象中都會(huì)有一個(gè)空的Session對(duì)象,該對(duì)象采用了懶初始化設(shè)計(jì),只有在真正執(zhí)行讀寫(xiě)操作時(shí)才會(huì)初始化。
  • model.Context?結(jié)構(gòu)體中的User?表示當(dāng)前登錄的用戶基本信息,只有在用戶登錄后才有數(shù)據(jù),否則是nil。
  • model.Context?結(jié)構(gòu)體中的Data?,用于存儲(chǔ)自定義的KV?變量,因此一般來(lái)說(shuō)開(kāi)發(fā)者無(wú)需再往context.Context?上下文變量中增加自定義的鍵值對(duì),而是直接使用model.Context?對(duì)象的這個(gè)Data屬性即可。

二、邏輯封裝

由于該上下文對(duì)象也是和業(yè)務(wù)邏輯相關(guān)的,因此我們需要通過(guò)service對(duì)象將上下文變量封裝起來(lái)以方便其他模塊使用。

// 上下文管理服務(wù)
var Context = new(contextService)

type contextService struct{}

// 初始化上下文對(duì)象指針到上下文對(duì)象中,以便后續(xù)的請(qǐng)求流程中可以修改。
func (s *contextService) Init(r *ghttp.Request, customCtx *model.Context) {
r.SetCtxVar(model.ContextKey, customCtx)
}

// 獲得上下文變量,如果沒(méi)有設(shè)置,那么返回nil
func (s *contextService) Get(ctx context.Context) *model.Context {
value := ctx.Value(model.ContextKey)
if value == nil {
return nil
}
if localCtx, ok := value.(*model.Context); ok {
return localCtx
}
return nil
}

// 將上下文信息設(shè)置到上下文請(qǐng)求中,注意是完整覆蓋
func (s *contextService) SetUser(ctx context.Context, ctxUser *model.ContextUser) {
s.Get(ctx).User = ctxUser
}

Tips

在架構(gòu)設(shè)計(jì)中,在哪個(gè)場(chǎng)景下設(shè)置Context是非常關(guān)鍵的。

上下文的變量必須在請(qǐng)求一開(kāi)始便注入到請(qǐng)求流程中,以便于其他方法調(diào)用,所以在中間件中來(lái)實(shí)現(xiàn)是非常優(yōu)雅的選擇。

我們來(lái)看下面的介紹:

三、上下文變量注入

在HTTP?請(qǐng)求中我們可以使用GoFrame的中間件來(lái)實(shí)現(xiàn)。

在GRPC請(qǐng)求中我們也可以使用攔截器來(lái)實(shí)現(xiàn)。

在service?層的middleware管理對(duì)象中,我們可以這樣來(lái)定義:

// 自定義上下文對(duì)象
func (s *middlewareService) Ctx(r *ghttp.Request) {
// 初始化,務(wù)必最開(kāi)始執(zhí)行
customCtx := &model.Context{
Session: r.Session,
Data: make(g.Map),
}
service.Context.Init(r, customCtx)
if userEntity := Session.GetUser(r.Context()); userEntity != nil {
customCtx.User = &model.ContextUser{
Id: userEntity.Id,
Passport: userEntity.Passport,
Nickname: userEntity.Nickname,
Avatar: userEntity.Avatar,
}
}
// 將自定義的上下文對(duì)象傳遞到模板變量中使用
r.Assigns(g.Map{
"Context": customCtx,
})
// 執(zhí)行下一步請(qǐng)求邏輯
r.Middleware.Next()
}

這個(gè)中間件,初始化了用戶執(zhí)行流程 共享的對(duì)象,并且存儲(chǔ)到context.Context?變量中的對(duì)象是指針類型*model.Context。

這樣做的好處是:任何一個(gè)地方獲取到這個(gè)指針,不僅可以獲取到里面的數(shù)據(jù),而且能夠直接修改里面的數(shù)據(jù)。

TIPS

如果Session?中存在用戶登錄后的存儲(chǔ)信息,那么也會(huì)將需要共享的用戶基本信息寫(xiě)入到*model.Context中。

四、上下文變量使用

方法定義

方法定義的第一個(gè)輸入?yún)?shù)往往預(yù)留給context.Context?類型參數(shù)使用,以便接受上下文變量,特別是service層的方法。

例如:

// 執(zhí)行用戶登錄
func (s *userService) Login(ctx context.Context, loginReq *define.UserServiceLoginReq) error {
...
}

// 查詢內(nèi)容列表
func (s *contentService) GetList(ctx context.Context, r *define.ContentServiceGetListReq) (*define.ContentServiceGetListRes, error) {
...
}

// 創(chuàng)建回復(fù)內(nèi)容
func (s *replyService) Create(ctx context.Context, r *define.ReplyServiceCreateReq) error {
...
}

TIPS

另外一個(gè)好習(xí)慣是:方法的最后一個(gè)返回參數(shù)往往是error?類型。如果確定方法內(nèi)部永不會(huì)產(chǎn)生error,那么可以忽略。

?Context??對(duì)象獲取

通過(guò)service?中封裝的以下方法,將context.Context上下文變量傳遞進(jìn)去即可。

context.Context?上下文變量在GoFrame?框架的HTTP?請(qǐng)求中可以通過(guò)r.Context()方法獲取。

在GRPC?請(qǐng)求中,編譯生成的pb?文件中執(zhí)行方法的第一個(gè)參數(shù)即固定是context.Context。

service.Context.Get(ctx)

自定義?Key-Value?

我們可以通過(guò)以下方式設(shè)置/獲取自定義的key-value鍵值對(duì)。

// 設(shè)置自定義鍵值對(duì)
service.Context.Get(ctx).Data[key] = value

// 獲取自定義鍵值對(duì)
service.Context.Get(ctx).Data[key]

五、注意問(wèn)題

上下文變量只傳遞必須的鏈路參數(shù)數(shù)據(jù),不要什么參數(shù)都往里面塞。特別是一些方法參數(shù)、傳參的數(shù)據(jù),千萬(wàn)不能往上下文里面塞,而應(yīng)當(dāng)用顯示的方式傳遞方法參數(shù)。

上下文變量?jī)H用作運(yùn)行時(shí)臨時(shí)使用,不可做持久化存儲(chǔ)長(zhǎng)期使用。

總結(jié)

這篇文章詳細(xì)的為大家介紹了GoFrame上下文對(duì)象Context的知識(shí)點(diǎn):

Context的作用:在業(yè)務(wù)流程中進(jìn)行變量的共享。

Context的結(jié)構(gòu)定義、邏輯封裝、如何在中間件中注入、如何通過(guò)Context設(shè)置值和取值、Context如何自定義key-value、以及在項(xiàng)目開(kāi)發(fā)中使用的注意問(wèn)題。

歡迎Star GoFrame:https://github.com/gogf/gf

本文轉(zhuǎn)載自微信公眾號(hào)「 程序員升級(jí)打怪之旅」,作者「王中陽(yáng)Go」,可以通過(guò)以下二維碼關(guān)注。

轉(zhuǎn)載本文請(qǐng)聯(lián)系「 程序員升級(jí)打怪之旅」公眾號(hào)。


文章標(biāo)題:GoFrame如何優(yōu)雅的共享變量?Context的使用
URL網(wǎng)址:http://www.5511xx.com/article/dhsghes.html