🔥 🔥 🔥 新鲜出炉!洋葱模型的管道实现,你还在愁 go 没有好用的中间件吗?

Goal-web/pipeline

goal-web/pipeline
这是一个管道库,实现了 和 laravel 一样的管道功能,如果你很熟悉 laravel 的管道或者中间件,那你一定对这个库很有亲切感。

安装 - install

go get github.com/goal-web/pipeline

使用 - usage

得益于 goal 强大的容器,你可以在管道(pipe)和目的地(destination)任意注入容器中存在的实例

对管道不熟悉的同学,可以把 pipe 理解为中间件,destination 就是控制器方法

package tests

import (
    "fmt"
    "github.com/goal-web/container"
    "github.com/goal-web/contracts"
    "github.com/goal-web/pipeline"
    "github.com/pkg/errors"
    "testing"
)

type User struct {
    Id   int
    Name string
}

func TestPipeline(t *testing.T) {
    pipe := pipeline.New(container.New())
    pipe.Send(User{Id: 1, Name: "goal"}).
        Through(
            func(user User, next pipeline.Pipe) interface{} {
                fmt.Println("中间件1-start")
                result := next(user)
                fmt.Println("中间件1-end")
                return result
            },
            func(user User, next pipeline.Pipe) interface{} {
                fmt.Println("中间件2-start")
                result := next(user)
                fmt.Println("中间件2-end")
                return result
            },
        ).
        Then(func(user User) {
            fmt.Println("then", user)
        })
}

// TestPipelineException 测试异常情况
func TestPipelineException(t *testing.T) {
    defer func() {
        recover()
    }()
    pipe := pipeline.New(container.New())
    pipe.Send(User{Id: 1, Name: "goal"}).
        Through(
            func(user User, next pipeline.Pipe) interface{} {
                fmt.Println("中间件1-start")
                result := next(user)
                fmt.Println("中间件1-end", result)
                return result
            },
            func(user User, next pipeline.Pipe) interface{} {
                fmt.Println("中间件2-start")
                result := next(user)
                fmt.Println("中间件2-end", result)
                return result
            },
        ).
        Then(func(user User) {
            panic(errors.New("报个错"))
        })
}

// TestStaticPipeline 测试调用magical函数
func TestStaticPipeline(t *testing.T) {
    // 应用启动时就准备好的中间件和控制器函数,在大量并发时用 StaticPipeline 可以提高性能
    middlewares := []contracts.MagicalFunc{
        container.NewMagicalFunc(func(user User, next pipeline.Pipe) interface{} {
            fmt.Println("中间件1-start")
            result := next(user)
            fmt.Println("中间件1-end", result)
            return result
        }),
        container.NewMagicalFunc(func(user User, next pipeline.Pipe) interface{} {
            fmt.Println("中间件2-start")
            result := next(user)
            fmt.Println("中间件2-end", result)
            return result
        }),
    }
    controller := container.NewMagicalFunc(func(user User) int {
        fmt.Println("then", user)
        return user.Id
    })

    pipe := pipeline.Static(container.New())
    result := pipe.SendStatic(User{Id: 1, Name: "goal"}).
        ThroughStatic(middlewares...).
        ThenStatic(controller)

    fmt.Println("穿梭结果", result)
    /**
    中间件1-start
    中间件2-start
    then {1 goal}
    中间件2-end [1]
    中间件1-end [1]
    穿梭结果 [1]
     */
}

// TestPurePipeline 测试纯净的 pipeline
func TestPurePipeline(t *testing.T) {
    // 如果你的应用场景对性能要求极高,不希望反射影响你,那么你可以试试下面这个纯净的管道
    pipe := pipeline.Pure()
    result := pipe.SendPure(User{Id: 1, Name: "goal"}).
        ThroughPure(
            func(user interface{}, next pipeline.Pipe) interface{} {
                fmt.Println("中间件1-start")
                result := next(user)
                fmt.Println("中间件1-end", result)
                return result
            },
            func(user interface{}, next pipeline.Pipe) interface{} {
                fmt.Println("中间件2-start")
                result := next(user)
                fmt.Println("中间件2-end", result)
                return result
            },
        ).
        ThenPure(func(user interface{}) interface{} {
            fmt.Println("then", user)
            return user.(User).Id
        })
    fmt.Println("穿梭结果", result)
    /**
    中间件1-start
    中间件2-start
    then {1 goal}
    中间件2-end 1
    中间件1-end 1
    穿梭结果 1
     */
}

在 goal 之外的框架使用 - use in frameworks other than goal

这个库并不会限制你在哪个框架使用它,所以你可以在任意 go 环境使用这个管道库

goal-web
goal-web/pipeline
qbhy0715@qq.com

本作品采用《CC 协议》,转载必须注明作者和本文链接
qbhy
讨论数量: 3
qbhy

最新的代码支持了纯净模式,进一步提高管道性能。文章已同步更新!

2年前 评论
qbhy

顶一个

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!