狂欢控制器的正确模式或技巧

时间:2019-07-13 15:15:20

标签: go model-view-controller revel

我正在尝试编写网络应用。我用于后端的技术栈是 Golang + Revel

应用程序的体系结构:

app/
   controllers/
      app.go
      authController.go
      init.go
   models/
      auth.go
   views/
      template.html
      login.html
...(etc)
routes.conf

我尝试遵循MVC的思想,但也想在逻辑上添加一些抽象,因此对我来说,将一些控制器包装到mainController(app.go)中将是很棒的选择

问题是nil指针的运行时错误。

Revel框架具有Interseptors,因此我可以在应用启动之前初始化任何控制器,并确保我不会将控制器与nil指针一起使用。

但是据我了解,每个控制器初始化都是分开的,这意味着我不能从另一个控制器调用控制器

我遇到的以下示例:

// app.go
package controllers

import (
    "fmt"
    "github.com/revel/revel"
    "webapp/models/auth"
)

type App struct {
    *revel.Controller
    a *AuthController
}

func (c *App) Init() *App {
    c.a = NewAuthController()
    return nil
}

func (c *App) Index() revel.Result {
    fmt.Println("App ->>>")
    if !c.a.CheckAuth(c.Request) {
        return c.Redirect("/auth")
    }
    return c.Render()
}

//----------------------------------
//authController.go

package controllers

import (
    "fmt"
    "github.com/revel/revel"
    "webapp/models/auth"
)

type AuthController struct {
    *revel.Controller
    auth *auth.Auth
}

func NewAuthController() *AuthController {
    return &AuthController{auth: auth.Init()}
}

func (c *AuthController) CheckAuth(request *revel.Request) bool {
    fmt.Println("AuthController::CheckAuth ->>>")
    return c.auth.CheckAuth()
}

func (c *AuthController) RenderAuthForm() revel.Result {
    fmt.Println("AuthController::Auth ->>>")
    return c.RenderTemplate("App/Index.html")
} 

func (c *AuthController) Login() revel.Result {
    fmt.Println("AuthController::Auth ->>>")
    fmt.Println(c.auth) // <<<<<<< -------
    return c.RenderTemplate("App/Index.html")
}


// auth.go
package auth

import (
    "errors"
    "fmt"
    "github.com/revel/revel"
    "github.com/revel/revel/cache"
    "strings"
)

type Auth struct {
    request *revel.Request
    token   string
}


func NewModel(request *revel.Request) (auth *Auth) {
    auth = new(Auth)
    auth.request = request
    return
}


func (c *Auth) CheckAuth() bool {
    fmt.Println("Auth::CheckAuth ->>>")
    return true
}

因此该代码可以编译并很好地运行,但是有两种通过不同途径调用的场景:

1) App::Index -> (calls own copy of AuthController) -> AuthController::CheckAuth -> (calls its own copy of AuthModel) -> AuthModel::CheckAuth
2) AuthController::Login -> (try to call own copy of AuthModel) -> Print = <nil>

所以问题是,如何组织代码以避免出现零指针错误?

0 个答案:

没有答案