21st
21st

Reputation: 2111

Golang log function return arguments

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?

Upvotes: 0

Views: 1944

Answers (3)

Jonathan Hall
Jonathan Hall

Reputation: 79584

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.

Upvotes: 1

stevenferrer
stevenferrer

Reputation: 2612

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

Upvotes: 0

Keeto
Keeto

Reputation: 4198

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

Upvotes: 2

Related Questions