Since the introduction of generics in Go 1.18, you can define the following generic function for composing two arbitrary functions:
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))
}
}
The order of composition of compose above is left to right, i.e., compose(f, g) returns the function "g after f" or g ∘ f, equivalent to g . f in Haskell and to f >> g in F# or Elm.
In other words, the input to the resulting function – compose(f, g) – is fed into f, then f's output is fed into g, whose output is the final result:

Let's first define the type Adapter for representing the type of functions you want to compose:
type Adapter = func(*Handle) *Handle
With compose and Adapter, you can now define composeAdapters for composing an arbitrary number of these Adapters functions:
func composeAdapters(adapters ...Adapter) Adapter {
composition := func(h *Handle) *Handle {
return h
}
for _, adapter := range adapters {
composition = compose(composition, adapter)
}
return composition
}
Note that composition is initialized to the identity function for *Handle. You can think of it as a no-op adapter: it just forwards the input to the resulting composed adapters to the first function to compose in the chain, if any. This also implies that calling composeAdapters without any arguments – e.g., composeAdapters() – results in the no-op adapter: it performs no action on the input *Handle; it just gives it back.
Given the functions f, g, and h of type Adapter – i.e., func(*Handle) *Handle – applyMiddleware can be implemented as:
var applyMiddleware = composeAdapters(f, g, h)
Note again the order of composition:

func(*Handle) *Handleotherwise it is not valid go code.