0

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?

5
  • 2
    Is this just during debugging, or you want this to be a feature of your production code? Commented Oct 13, 2017 at 7:35
  • both, I'm currently developing in a kubernetes cluster and don't get a debugger running there and for production it's cool as you can get log based metrics really simple Commented Oct 13, 2017 at 9:04
  • 1
    and thanks for removing my greeting ✌️😢 Commented Oct 13, 2017 at 9:05
  • lol.... generally greetings and closings are considered extraneous here. Not because we don't like being polite, but more because we just like to get to the point of the question. Commented Oct 13, 2017 at 10:32
  • true that, good point Commented Oct 13, 2017 at 11:05

3 Answers 3

2

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)
}
Sign up to request clarification or add additional context in comments.

5 Comments

@Keeto, should you be returning nil instead of err? play.golang.org/p/_xcRpfC9u-
@srxf I just chose to return nil because my function body has no errors. You could return whatever you want. The defer function will pick on whatever the values of the return variables are and and log them or do any kind of processing on them
dope, that's a nice one.. def +1, I will wait 7 more days and if nobody comes up with sth smarter I'll accept your answer, thanks man! :)
Should it be just defer log.Printf("%v %v %v %v", a, b, c, err)?
@AlexanderTrakhimenok na, arguments passed to defer are evaluated instantly, so you would get c == 0 and err == nil.. with the func the arguments are evaluated once the func is executed
1

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\n", 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\n", 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.

Comments

0

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\n", 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)
}

1 Comment

cool idea, I don't like that you gotta write a "Logger" for every function signature though

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.