? ? ? 新鮮出爐!洋蔥模型的管道實現,你還在愁 go 沒有好用的中介軟體嗎?

qbhy發表於2022-01-29

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 協議》,轉載必須註明作者和本文連結

相關文章