Home >Backend Development >Golang >How to Create a Function Wrapper in Go to Inject Code Before and After Execution?

How to Create a Function Wrapper in Go to Inject Code Before and After Execution?

DDD
DDDOriginal
2024-12-03 00:56:11229browse

How to Create a Function Wrapper in Go to Inject Code Before and After Execution?

Function Wrapper in Go

Question:

How can I create a function wrapper in Go to inject code before and after a function execution?

Answer:

In Go, it's possible to create a function wrapper that takes a function as an argument and returns a new function value. This allows for injecting code before and after the call to the wrapped function.

Here's an example of a wrapper function:

func funcWrapper(myFunc interface{}) {
    fmt.Println("Before")
    // Call myFunc
    fmt.Println("After")
}

Wrapped Function with Signature:

If you know the signature of the function to be wrapped, you can create a wrapper function that takes a function value of that type and returns another function value of the same type. This is exemplified below:

func wrap(f func(i int) int) func(i int) int {
    return func(i int) (ret int) {
        fmt.Println("Before, i =", i)
        ret = f(i)
        fmt.Println("After, ret =", ret)
        return
    }
}

Supporting Multiple Function Types:

To support multiple function types, you can create separate wrapper functions for each distinct type:

func wrap(f func()) func() {
    return func() {
        fmt.Println("Before func()")
        f()
        fmt.Println("After func()")
    }
}

func wrapInt2Int(f func(i int) int) func(i int) int {
    return func(i int) (ret int) {
        fmt.Println("Before func(i int) (ret int), i =", i)
        ret = f(i)
        fmt.Println("After func(i int) (ret int), ret =", ret)
        return
    }
}

Generic Wrapper Using Reflection:

While Go lacks generics, a more generic approach using reflection is possible:

func wrap(f interface{}) interface{} {
    switch f2 := f.(type) {
    case func(i int) (ret int):
        return func(i int) (ret int) {
            fmt.Println("Before func(i int) (ret int), i =", i)
            ret = f2(i)
            fmt.Println("After func(i int) (ret int), ret =", ret)
            return
        }
    case func():
        return func() {
            fmt.Println("Before func()")
            f2()
            fmt.Println("After func()")
        }
    }
    return nil
}

However, this approach uses an interface{} return type and requires type assertions when using it.

Example Usage:

wf := wrap(myfunc).(func(int) int)
ret := wf(2)
fmt.Println("Returned:", ret)

Output:

Before, i = 2
myfunc called with 2
After, ret = 4
Returned: 4

The above is the detailed content of How to Create a Function Wrapper in Go to Inject Code Before and After Execution?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn