Gin 系列讲座: Saas系统, Gin+Jwt+casbin RestFul Api 后端一战到底 1: Gin Context 详解

3,036 阅读2分钟

1 Gin 系列讲座: Saas系统, Gin+Jwt+casbin RestFul Api 后端一战到底

1: Gin Context 详解

标准Context

golang 1.7 中官方给出了Context实现, 尤其在Gin中 其中点是可以链式传递共享变量. 我们只所以先讲Context, 是为了大家便于理解 Gin中如何将jwt 的token ID ,以及用户ID . 保存到 自定义的context中. 或者TraceID. 这样在后面的多个Goroutine中 共享, 另外一个重点是这些都是基于 gin 中间件实现.!这样在工程中非常便利.

自定义扩展Context


import (
	"context"
)

// 定义全局上下文中的键
type (
	transCtx   struct{}
	userIDCtx  struct{}
	traceIDCtx struct{}
)

// NewTrans 创建事务的上下文
func NewTrans(ctx context.Context, trans interface{}) context.Context {
	return context.WithValue(ctx, transCtx{}, trans)
}

// FromTrans 从上下文中获取事务
func FromTrans(ctx context.Context) (interface{}, bool) {
	v := ctx.Value(transCtx{})
	return v, v != nil
}

// NewUserID 创建用户ID的上下文
func NewUserID(ctx context.Context, userID string) context.Context {
	return context.WithValue(ctx, userIDCtx{}, userID)
}

// FromUserID 从上下文中获取用户ID
func FromUserID(ctx context.Context) (string, bool) {
	v := ctx.Value(userIDCtx{})
	if v != nil {
		if s, ok := v.(string); ok {
			return s, s != ""
		}
	}
	return "", false
}

// NewTraceID 创建追踪ID的上下文
func NewTraceID(ctx context.Context, traceID string) context.Context {
	return context.WithValue(ctx, traceIDCtx{}, traceID)
}

// FromTraceID 从上下文中获取追踪ID
func FromTraceID(ctx context.Context) (string, bool) {
	v := ctx.Value(traceIDCtx{})
	if v != nil {
		if s, ok := v.(string); ok {
			return s, s != ""
		}
	}
	return "", false
}

NewUserID

的意思是根据 输入的用户ID 产生一个新的Context, userIDCtx为key, userID为 value 保存到 context中欧给你 并将返回的context return

在gin contxt使用自定义context.

func NewContext(c *gin.Context) context.Context {
	parent := context.Background()

	if v := GetTraceID(c); v != "" {
		parent = icontext.NewTraceID(parent, v)
		parent = logger.NewTraceIDContext(parent, GetTraceID(c))
	}

	if v := GetUserID(c); v != "" {
		parent = icontext.NewUserID(parent, v)
		parent = logger.NewUserIDContext(parent, v)
	}

	return parent
}

上面的 icontext 就是我们自定义的context.

理解了这个就可以将我们自定义的context与gin 联系起来.

gin 中间件使用自定义context

return func(c *gin.Context) {
		var userID string
		if t := xxx.GetToken(c); t != "" {
			id, err

理解中中间件.

很多人感觉好像中间件很高大上, 其实就是一个 next -> next 不停的递归回调而已. 所以子要return func*(c *ginContext) 返回类型 gin.HandlerFunc. 一般都是中间件, 简单理解就是执行一个动作后, 中间在加一步,向拨开洋葱一样