如何在go中组合函数?

jv4diomz  于 2023-05-27  发布在  Go
关注(0)|答案(2)|浏览(174)

我试图弄清楚如何设置中间件,现在我有这样的东西:

func applyMiddleware(h *Handle) *Handle {
   return a(b(c(h)))
}

有没有一种方法可以“组合”这些函数,这样我就可以只传递一个Handle列表,它就会返回组合后的函数?

pcrecxhr

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
    }
}
ohfgkhjo

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,其输出是最终结果:

让我们首先定义Adapter类型,用于表示您想要组合的函数类型:

type Adapter = func(*Handle) *Handle

使用composeAdapter,现在可以定义composeAdapters来组合任意数量的Adapter s函数:

func composeAdapters(adapters ...Adapter) Adapter {
    composition := func(h *Handle) *Handle {
        return h
    }
    for _, adapter := range adapters {
        composition = compose(composition, adapter)
    }
    return composition
}

注意composition被初始化为*Handleidentity function。你可以把它想象成一个 *no-op适配器 *:它只是将输入转发到所产生的组合适配器,并转发到链中要组合的第一个函数(如果有的话)。这也意味着不带任何参数调用composeAdapters(例如composeAdapters())会导致no-op适配器:它不对输入*Handle执行任何操作;它就会把它还给你
给定类型为Adapter的函数fgh,即func(*Handle) *Handle-applyMiddleware可以实现为:

var applyMiddleware = composeAdapters(f, g, h)

再次注意组成顺序:

相关问题