大话 Iris

Go 目前并不支持动态生成结构体类型这类元编程API,因此无法如Java的Spring那样通过注解或xml配置,“动态”生成代理类类型,更不要说 laravel 这种强依赖 ioc 容器控制反转。但基于反射,它还是可以做到部分依赖注入,比如 路径参数类型注入,基于函数类型配置的延迟绑定....。在Iris框架的MVC应用中,控制器的依赖是通过自动复制传递给“子类”

自动路由

Golang标准库net\http 是web网络编程的底层支柱。如同所有web编程,handler 接受一个请求,返回一个响应。Iris框架的mvc则更多的是围绕路由来做文章。iris中的控制器本质是一个持有特定后缀的结构体,该结构体持有iris特定的前缀或后缀方法,以便在通过反射生成对应的HTTP谓词Handler。这种情况,与java标准接口一致,get,post之类打头,与早期版本laravel写法一样。当然也支持定义路由,及相关的类初始与结束方法。

依赖管理

在spring中可用注解或xml,甚至是java代码配置,来规则化对象的创建及管理。Iris框架中的对象,创建与管理需要手动维护。比如,像在laravel这种高度依赖容器的框架中,需要某个功能服务,通常注册服务提供者,后从ioc容器中拿出来用。但在Iris中对象与对象之间,依赖的维护,对象创建关系,通常是代码显性呈现。最初的实例创建,并不适合一 New了之。Irish搞了一些动态绑定,要么将接收器作为函数的第一参数,要么自带隐式依赖复制。所以也就不难奇怪,有许多configurator 参数配置都是一个个持有app实例的函数变量,本质上还是在创建的对象实例变更状态。当然所这一切,都是监听之前完成。

函数 vs 方法

纯函数暂且不论,那些会产生副作用的函数,往往是某个结构体的方法的变种。这是因为对于接收参数为引用类型的函数而言,在其内部是有机会改变外部引用对象的状态,或执行它的方法。这种特性与语言无关,只不过在Go这种面向接口的编程语言iris框架中被放大了。

class A {...}
a = new A
a.name = "pardon110"

// 在iris中做法通常这样
type A struct{...}
app = &A{....}
func configurator(a *A){
    a.port = "8080"
}
// 后其配置
app.configure(configurator...)

看起来,点麻烦,实际上这种绑定的操作行为,就有更多的可变性,况且在Go中函数还是一等公民。

控制器

package main

import (
    "github.com/kataras/iris"
    "github.com/kataras/iris/middleware/logger"
    "github.com/kataras/iris/middleware/recover"
    "github.com/kataras/iris/mvc"
)

func main() {
    app := newApp()
    app.Run(iris.Addr(":8080"))
}

func newApp() *iris.Application {
    app := iris.New()
    // 可选的 或选的handler
    app.Use(recover.New())
    app.Use(logger.New())

    mvc.New(app).Handle(new(ExampleController))
    return app
}

// ExampleController  /
type ExampleController struct{}

// Get serves
// Method:   GET
// Resource: http://localhost:8080
func (c *ExampleController) Get() mvc.Result {
    return mvc.Response{
        ContentType: "text/html",
        Text:        "<h1>Welcome</h1>",
    }
}

// GetPing serves
// Method:   GET
// Resource: http://localhost:8080/ping
func (c *ExampleController) GetPing() string {
    return "pong"
}

// GetHello serves
// Method:   GET
// Resource: http://localhost:8080/hello
func (c *ExampleController) GetHello() interface{} {
    return map[string]string{"message": "Hello Iris!"}
}

// BeforeActivation 一次性调用,在主程执行之前
// v9版本之后 可在该方法内对控制器方法指定自定义的路由
// 也可用 `b.Router` 访问不带MVC的标准 router
// 还可给控制器字段 或 方法的输入参数 增加依赖
func (c *ExampleController) BeforeActivation(b mvc.BeforeActivation) {

    anyMiddlewareHere := func(ctx iris.Context) {
        ctx.Application().Logger().Warnf("内部自定义 /cutstom_path")
        ctx.Next()
    }
    // 自定义路由,无需遵守命名规则
    b.Handle("GET", "/custom_path", "CustomHandlerWithoutFollowingTheNamingGuide", anyMiddlewareHere)
    // 或添加该控制器的全局中间件  比如使用根 /
    // b.Router().Use(myMiidleware)
}

// CustomHandlerWithoutFollowingTheNamingGuide serves
// Method:   GET
// Resource: http://localhost:8080/custom_path
func (c *ExampleController) CustomHandlerWithoutFollowingTheNamingGuide() string {
    return "hello from the custom handler without following the naming guide"
}

// GetUserBy serves
// Method:   GET
// Resource: http://localhost:8080/user/{username:string}
// By 关键字告知框架 路径参数绑定
//
func (c *ExampleController) GetUserBy(username string) mvc.Result {
    return mvc.View{
        Name: "user/username.html",
        Data: username,
    }
}

/* 工厂方法将HTTP谓词正确绑定到对应路由
func (c *ExampleController) Post() {}
func (c *ExampleController) Put() {}
func (c *ExampleController) Delete() {}
func (c *ExampleController) Connect() {}
func (c *ExampleController) Head() {}
func (c *ExampleController) Patch() {}
func (c *ExampleController) Options() {}
func (c *ExampleController) Trace() {}
*/

/*
func (c *ExampleController) All() {}
//        OR
func (c *ExampleController) Any() {}
*/

// AfterActivation  所有依赖被配置完毕,但仍可添加标准handler
func (c *ExampleController) AfterActivation(a mvc.AfterActivation) {}
本作品采用《CC 协议》,转载必须注明作者和本文链接
pardon110
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
开发者 @ 社科大
文章
134
粉丝
24
喜欢
103
收藏
56
排名:105
访问:8.9 万
私信
所有博文
社区赞助商