我试图弄清楚如何设置中间件,现在我有这样的东西:
func applyMiddleware(h *Handle) *Handle { return a(b(c(h))) }
有没有一种方法可以“组合”这些函数,这样我就可以只传递一个Handle列表,它就会返回组合后的函数?
pcrecxhr1#
使用切片https://play.golang.org/p/DrEnGkIEbU3
package main import ( "fmt" ) func main() { fmt.Println(v(v(v(0)))) fmt.Println(compose(v, v, v)(0)) } func v(i int) int { return i + 1 } func compose(manyv ...func(int) int) func(int) int { return func(i int) int { for _, v := range manyv { i = v(i) } return i } }
ohfgkhjo2#
自从Go 1.18中引入泛型以来,您可以定义以下泛型函数来组合两个任意函数:
func compose[A any, B any, C any](f func(A) B, g func(B) C) func(A) C { return func(a A) C { return g(f(a)) } }
上面的compose的组合顺序是 * 从左到右 *,即compose(f, g)返回函数“g after f”或 g**f,相当于Haskell中的g . f和F#或Elm中的f >> g。换句话说,结果函数-compose(f, g)-的输入被馈送到f,然后f的输出被馈送到g,其输出是最终结果:
compose
compose(f, g)
g . f
f >> g
f
g
让我们首先定义Adapter类型,用于表示您想要组合的函数类型:
Adapter
type Adapter = func(*Handle) *Handle
使用compose和Adapter,现在可以定义composeAdapters来组合任意数量的Adapter s函数:
composeAdapters
func composeAdapters(adapters ...Adapter) Adapter { composition := func(h *Handle) *Handle { return h } for _, adapter := range adapters { composition = compose(composition, adapter) } return composition }
注意composition被初始化为*Handle的 identity function。你可以把它想象成一个 *no-op适配器 *:它只是将输入转发到所产生的组合适配器,并转发到链中要组合的第一个函数(如果有的话)。这也意味着不带任何参数调用composeAdapters(例如composeAdapters())会导致no-op适配器:它不对输入*Handle执行任何操作;它就会把它还给你给定类型为Adapter的函数f、g和h,即func(*Handle) *Handle-applyMiddleware可以实现为:
composition
*Handle
composeAdapters()
h
func(*Handle) *Handle
applyMiddleware
var applyMiddleware = composeAdapters(f, g, h)
再次注意组成顺序:
2条答案
按热度按时间pcrecxhr1#
使用切片
https://play.golang.org/p/DrEnGkIEbU3
ohfgkhjo2#
自从Go 1.18中引入泛型以来,您可以定义以下泛型函数来组合两个任意函数:
上面的
compose
的组合顺序是 * 从左到右 *,即compose(f, g)
返回函数“g after f”或 g**f,相当于Haskell中的g . f
和F#或Elm中的f >> g
。换句话说,结果函数-
compose(f, g)
-的输入被馈送到f
,然后f
的输出被馈送到g
,其输出是最终结果:让我们首先定义
Adapter
类型,用于表示您想要组合的函数类型:使用
compose
和Adapter
,现在可以定义composeAdapters
来组合任意数量的Adapter
s函数:注意
composition
被初始化为*Handle
的 identity function。你可以把它想象成一个 *no-op适配器 *:它只是将输入转发到所产生的组合适配器,并转发到链中要组合的第一个函数(如果有的话)。这也意味着不带任何参数调用composeAdapters
(例如composeAdapters()
)会导致no-op适配器:它不对输入*Handle
执行任何操作;它就会把它还给你给定类型为
Adapter
的函数f
、g
和h
,即func(*Handle) *Handle
-applyMiddleware
可以实现为:再次注意组成顺序: