文章目录
- Context
- 结构定义
- 逻辑封装
- 上下文变量注入
- 上下文变量使用
官方文档: Context: 业务流程共享变量 - GoFrame (ZH)-Latest - GoFrame官网 - 类似PHP-Laravel, Java-SpringBoot的Go企业级开发框架
Context
在Go的执行流程中,不存在全局变量
这种获取请求参数的方式,但可以通过上下文Context将所有需要传递的共享变量传递到后续流程的方法中。
结构定义
结构体中需要包含业务中传递的信息,这里包含了会话(Session)、用户信息(User)以及一个键值对映射(Data)。
新建model/context.go
文件:
├── model
│ | ├── do
│ │ ├── entity
│ │ └── context.go
package modelimport ("github.com/gogf/gf/v2/frame/g""github.com/gogf/gf/v2/net/ghttp"
)const (// 上下文变量存储键名,前后端系统共享ContextKey = "ContextKey"
)// 请求上下文结构
type Context struct {Session *ghttp.Session // 当前Session管理对象User *ContextUser // 上下文用户信息Data g.Map // 自定KV变量,业务模块根据需要设置,不固定
}// 请求上下文中的用户信息
type ContextUser struct {Id uint // 用户IDPassport string // 用户账号Nickname string // 用户名称Avatar string // 用户头像
}
逻辑封装
封装上下文的相关操作。这包括初始化上下文、获取上下文和设置用户信息等功能。
新建logic/context/context.go
文件
├── logic
│ │ ├── context
│ │ │ └── context.go
│ │ └── logic.go
package contextimport ("context""demo/internal/model""demo/internal/service""github.com/gogf/gf/v2/net/ghttp"
)func init() {service.RegisterContext(New())
}type sContext struct{}func New() *sContext {return &sContext{}
}// 初始化上下文对象指针到上下文对象中,以便后续的请求流程中可以修改。
func (s *sContext) Init(r *ghttp.Request, customCtx *model.Context) {r.SetCtxVar(model.ContextKey, customCtx)
}// 获得上下文变量,如果没有设置,那么返回nil
func (s *sContext) 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
}// 将上下文信息设置到上下文请求中,注意是完整覆盖
func (s *sContext) SetUser(ctx context.Context, ctxUser *model.ContextUser) {s.Get(ctx).User = ctxUser
}
上下文变量注入
上下文变量的注入通过定义一个中间件来实现。这个中间件在请求的最开始执行,用于初始化上下文,将请求中携带的参数置入结构体中,以便后续的处理函数可以便捷调用。
新建logic/middleware/middleware.go
文件
├── logic
│ │ ├── context
│ │ ├── middleware
│ │ │ └── middleware.go
│ │ └── logic.go
package middlewareimport ("demo/internal/model""demo/internal/service""github.com/gogf/gf/v2/frame/g""github.com/gogf/gf/v2/net/ghttp"
)type sMiddleware struct{}func init() {service.RegisterMiddleware(New())
}func New() *sMiddleware {return &sMiddleware{}
}func (*sMiddleware) Ctx(r *ghttp.Request) {// 初始化,务必最开始执行customCtx := &model.Context{Session: r.Session,Data: make(g.Map),}service.Context().Init(r, customCtx)// TODO 获取用户信息// ...// 将自定义的上下文对象传递到模板变量中使用r.Assigns(g.Map{"Context": customCtx,})// 执行下一步请求逻辑r.Middleware.Next()
}
上下文变量使用
约定方法定义的第一个输入参数预留给context.Context类型参数使用,以便接受上下文变量。例如:
func (s *xxx) func1(ctx context.Context, xxxxReq *xxx.xxxxReq) error {...
}
可以通过以下方式获取上下文:
service.Context().Get(ctx)
可以通过 Data 字段存储和获取自定义的键值对数据:
// 设置自定义键值对
service.Context.Get(ctx).Data[key] = value
// 获取自定义键值对
service.Context.Get(ctx).Data[key]