如何实现类似继承的效果
在iris的mvc架构中,我有一组XxxController
结构体,每个结构体都需要实现一个auth()
方法,为了简便,我尝试所有结构体引入一个名为BaseController
的结构体,这样我就可以在各个XxxController
里使用这个方法了,代码如下:
//BaseController 根结构体
type BaseController struct {
Ctx iris.Context
UserClaims middleware.UserClaims
}
func (b *BaseController) auth() middleware.UserClaims {
if b.UserClaims.ID > 0 {
return b.UserClaims
}
mc := b.Ctx.Values().Get("jwt").(*jwt.Token).Claims.(jwt.MapClaims)
return middleware.UserClaims{
Nickname: mc["nickname"].(string),
ID: uint(mc["id"].(float64)),
Issuer: mc["iss"].(string),
IssuedAt: int64(mc["iat"].(float64)),
JwtId: mc["jti"].(string),
NotBefore: int64(mc["nbf"].(float64)),
ExpiresAt: int64(mc["exp"].(float64)),
}
}
//TestController 子结构体
type TestController struct {
BaseController
Service *services.TestService
}
func NewTestController() *TestController {
return &TestController{Service: services.NewTestService()}
}
func (t *TestController) PostSave() (r models.Result) {
fmt.Println("PostSave")
var test models.Test
if err := t.Ctx.ReadJSON(&test); err != nil {
t.Ctx.StopWithError(iris.StatusBadRequest, err)
return models.Result{
Code: models.CodeFail,
Msg: "fail",
}
}
r.Data=test
r.Auth=t.auth()//直接在子结构体里调用父结构体的方法
return
}
我以为这样调用是可行的,但事实上请求会返回一个400错误,返回内容如下:
readObjectStart: expect { or n, but found ▯ , error found in #0 byte of ...||..., bigger context ...||...
是否有大神知道这种情况怎么解
2021年10月27日10点03分:新进展
我发现iris
的配置里DisableBodyConsumptionOnUnmarshal
设置为true
后我上面的模式也可以实现,这个配置百度翻译是:如果此字段设置为true,则将创建一个新的缓冲区来读取和请求正文。不会更改正文,并且不会使用context.UnmarshalBody/ReadJSON/ReadXML之前的现有数据
,依然感谢各位大神的指点,‘@滚球兽进化’的方案仍旧是极好的
iris 应该有中间件。 或者你自己去丰富这个请求的生命周期。你的需求是在每个控制器的逻辑执行前执行指定逻辑。其实就是 1 -> {} -> 逻辑 -> end 。你从这个角度看的话,实现的方法就多种多样了。我用gin写的时候因为觉得用 context 上设置 user 不太好,就写了个函数把传递过去的控制器方法处理成高阶函数,然后把控制器改造成想要的 request 参数