gin 是一个流行的 golang webserver 的框架。https://github.com/gin-gonic/gin
gin 中 HandlerFunc
(type HandlerFunc func(*Context)
) 的使用随处可见, ex. Middleware , Handler 中。
router.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
})
因此,根据之前 golang context 实现 IoC 容器经验, 使用 *gin.Context
作为 IoC 容器再好不过了。
标准库 context.Context
是一个接口(interface), gin.Context
是 gin 工程自己封装的的一个 struct, 并实现了该接口。虽然如此, 在实现的的时候, 还是有一点差别。
context.WithValue
将 key,val
写入 ctx
中并生成一个新的 Context
gin.Context
Set
方法, 原 ctx
增加新字段,保持。interface{}
, 可以存储任意类型。string
, 有所限制。// 标准库 函数
func WithValue(parent Context, key, val interface{}) Context
// gin.Context 方法
func (c *Context) Set(key string, value interface{})
context.Context.Value(key interface{}) interface{}
方法。gin.Context.Get(key string) interface{}
方法, 并且返回值多一个 bool 类型的 exists
参数返回, 可以判断 key 值是否存在, 排除 零值 的干扰。// 标准库
db := ctx.Value("db"
// gin
// db := c.Value("db") // 实现了 Context 接口, 可以。
db, exists := c.Get("db")
if !exists {
return
}
context ioc
传入到每一个函数 或 方法中。gin context ioc
传入。// 标准库
//
func save(ctx context.Context) {
// ...
}
// gin
func main() {
r := gin.Default()
r.Use(GinContextIoC) // 使用 middleware 的方式在 context 中注入与传递
// ...
}
这是一个实现了 gin context ioc 容器的 demo
golang demo 源代码 https://tangx.in/images/post/2021/07/28/gin-context-ioc/gin-context-ioc.go