how do you log function call return values in golang

huangapple go评论79阅读模式
英文:

how do you log function call return values in golang

问题

我想知道在退出一个Go函数时的返回值。Go语言的defer机制很有帮助,但它在注册defer语句时评估参数,而不是在执行时评估。我可以通过使用一个匿名函数来访问返回值来解决这个问题:

func try() (i int) {
  defer func() {fmt.Printf("%d", i)}()
  i = 10
  return i+1
}

func main() {
  try()
}

我认为这样可以正常工作,但我希望以一种通用的方式处理这个问题,也许像这样:

func try(in string) (out int) {
  enter("%s", in);exit("%d", out)
}

或者,更好的是,使用反射来输出进入/退出时的参数/返回值。我假设运行时性能不是关键 :).

有没有一种好的方法来做到这一点?Shaba Abhiram的Tracey库在很大程度上可以实现这一点,但没有打印返回值。

英文:

I want to know the return values at time of exit from a golang function. The golang defer mechanism is helpful, but it evaluates arguments at the time the defer statement is registered rather than when it is executed. I can work with this using an anonymous function which accesses the return values:

func try() (int i) {
  defer func() {fmt.Printf("%d", i)}()
  i = 10
  return i+1
}

func main() {
  try()
}

This would work ok, i think, but I would like to handle this in a generic manner, perhaps something like:

func try(in string) (out int) {
  enter("%s", in);exit("%d", out)
}

or, even better, use reflection to output the arguments/return values at time of entry/exit. I'm assuming runtime performance isn't critical :).

Is there a good way to do this? Shaba Abhiram's handy Tracey lib does go a long way towards this but stops short of printing the return values.

答案1

得分: 3

你在评估中是正确的,延迟函数的参数在延迟被排队时进行求值,而不是在执行时进行求值。

你使用匿名函数引用命名返回值的方法是有效的。另一种方法是传递返回值的地址

func try() (i int) {
    defer printReturns(time.Now(), &i)
    time.Sleep(10 * time.Millisecond)
    i = 10
    return i + 1
}

func printReturns(start time.Time, rets ...interface{}) {
    fmt.Println(time.Now().Sub(start))
    for _, ret := range rets {
        fmt.Println(ret)
    }
}

这种方法的问题是,你的日志函数现在有一个指针而不是真实类型,并且必须解引用指针才能对其进行任何操作。但如果你使用reflect,那就不是非常困难。

英文:

You are correct in assesing that the arguments to a deferred function are evaluated at the point the defer is queued, not when it is executed.

Your method of making an anonymous function that refers to named returns is valid. Another approach is to pass in the address of the return values:

func try() (i int) {
    defer printReturns(time.Now(), &i)
    time.Sleep(10 * time.Millisecond)
    i = 10
    return i + 1
}

func printReturns(start time.Time, rets ...interface{}) {
    fmt.Println(time.Now().Sub(start))
    for _,ret := range rets{
	    fmt.Println(ret)
    }
}

The problem with this approach is that your logging function now has a pointer instead of the real type and must unwrap the pointers to do anything with them. But if you are using reflect, that is not horribly difficult.

答案2

得分: 2

你可以使用godebug来实现最接近的效果,而不需要添加大量的printf语句。它基本上会为你添加printf语句。

英文:

The closest thing you will get to do it without adding a lot of printf's is using godebug, which pretty much adds the printfs for you.

huangapple
  • 本文由 发表于 2015年4月26日 06:47:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/29871585.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定