Golang日志函数返回参数

I would like to log a function's return values. The "smartest" thing I could come up with is wrapping my actual function body in a closure.

func foo(a int, b int) (int, error) {
    c, err := func (a int, b int) (int, error) {
        //...
        return c, err
    }(a, b)

    fmt.Printf("%v %v %v %v", a, b, c, err)

    return c, err
}

Is there a way to accomplish this with less boilerplate?

Maybe I misunderstood your question, but what about:

package main

import (
    "log"
)

func foo(a, b int) (c int, err error) {
    defer func() {log.Printf("%v %v %v %v", a, b, c, err)}()
    c = a + b
    return c, nil
}


func main() {
    foo(1, 3)
}

Try this one: https://play.golang.org/p/VrPgH1VUwP

Basically, you just have to wrap them with some function that returns a function with the same signature but including the logging:

type fooFunc func(int, int) (int, error)

func fooLogger(f fooFunc) fooFunc {
    return func(a, b int) (int ,error){
        c, err := f(a, b)
        log.Printf("%s => a: %v, b: %v, return => c: %v, err: %v
", fnName(f), a, b, c, err);
        return c, err
    }
}

func foo(a, b int) (int, error){
    c := a + b
    return c, nil
}


func main() {
    loggedFoo := fooLogger(foo)

    //prints something like this
    //2009/11/10 23:00:00 main.foo => a: 2, b: 2, return => c: 4, err: <nil>
    c, err := loggedFoo(2, 2)
    fmt.Println("from foo:", c, err)
}

There are two patterns I would consider:

  1. As @Keeto suggests, you can use a 'defer' statement:

    func foo(a, b int) (c int, e error) {
        defer log.Printf("%v %v %v %v
    ", a, b, c, err)
        // ... the function body
    }
    
  2. A logging stub function:

    func foo(a, b int) (int, error) {
        c, err := realFoo(a, b)
        log.Printf("%v %v %v %v
    ", a, b, c, err)
    }
    
    func realFoo(a, b int) (int, error) {
        // ... the function body
    }
    

A closure also works, as you mentioned in your question, but in my opinion, that's the least readable of the options.

Which you choose depends mainly on preference. Performance should be roughly the same across the three options--but if performance is critical, do benchmarks to be sure, under your real application load.