🔥 🔥 🔥 新鲜出炉! go 版本的 pipeline 发布啦,你还在愁 go 没有好用的中间件吗?

2022-01-29 10:38:55 +08:00
 qbhy

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]
	 */
}

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

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

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

3733 次点击
所在节点    Go 编程语言
16 条回复
qbhy
2022-01-29 10:40:09 +08:00
其实也不是那么新鲜了,因为是昨天晚上写好的了,早上起来才发的 V2
bthulu
2022-01-29 11:20:42 +08:00
中间件是不是就类似 java 里的过滤器, 为什么要叫中间件这个名字呢, 感觉好诡异
ccppgo
2022-01-29 11:37:16 +08:00
@bthulu PHP 的概念吧,middleware
qbhy
2022-01-29 14:09:48 +08:00
@bthulu 只是名字而已吧哈哈,本质上是一个东西,最多可能实现方式不一样
liuxu
2022-01-29 14:53:52 +08:00
@bthulu shell 里叫管道,iptables 叫表 /链,都不是以 java 的标准起的名字
xz410236056
2022-01-29 14:58:30 +08:00
@bthulu #2 过滤器是 Filter , 中间件可以 Filter 可以 map ,还可以干别的,你觉得叫什么合适呢
zoharSoul
2022-01-29 14:58:33 +08:00
理解为中间件是什么意思?

中间件不是指比如 rpc, mq, 配置中心, apm, 链路追踪之类的周边设施吗?
liuxu
2022-01-29 15:12:03 +08:00
@zoharSoul 其实没必要这么抠字眼,中间件是个思想,不是具体组件

可以看看红帽的文档
https://www.redhat.com/zh/topics/middleware/what-is-middleware

中间件是为应用提供通用服务和功能的软件。数据管理、应用服务、消息传递、身份验证和 API 管理通常都要通过中间件。
zoharSoul
2022-01-29 15:13:59 +08:00
@liuxu #8 对我也是这么理解的, 所以楼主的这个不是中间件
liuxu
2022-01-29 15:36:00 +08:00
@zoharSoul 对的,楼主只是为了没用过 linux 管道的人方便理解,类比了中间件的思想,要是楼主也写过 java ,原话应该会是:

可以理解成 laravel 的中间件,java 的 filter

插件名,类名 /结构名写的就是管道 pipeline


顺便给 phper 提一下,laravel 有中间件,而调用中间件方法和 controller 是框架底层的 Pipeline 类
bigpigeon
2022-01-29 17:04:01 +08:00
和 gin 的 middleware 区别在哪里
qbhy
2022-01-29 17:58:56 +08:00
我赞成八楼老哥的,中间件是思想,不是具体的组件。
qbhy
2022-01-29 18:01:01 +08:00
@bigpigeon 我这个管道库不是某个框架的中间件,只是洋葱模型的管道的一个实现,只是通常用来实现中间件功能。也就是说,你可以在任何需要用到管道的地方使用他,不局限于 gin 或者 goal 或者其他框架
qbhy
2022-01-30 00:14:14 +08:00
最新的版本支持了纯净模式,也就是没有容器的管道,因为没有反射,性能更好,但是也没有了依赖注入功能。
js2854
2022-02-09 13:50:03 +08:00
好像有现成的轮子,[RxGo]( https://github.com/ReactiveX/RxGo)
qbhy
2022-02-09 15:52:32 +08:00
@js2854 还是不太一样,我这个主要是需要容器注入功能,框架中许多地方用到

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/831235

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX