我正在尝试编写网络应用。我用于后端的技术栈是 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>
所以问题是,如何组织代码以避免出现零指针错误?