获取函数返回的行号

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

Get line number on which function returned

问题

从调用范围返回的函数是否可能获取行号?

示例:

func callee() error {
  if cond {
    return errors.New("whoops!")
  }
  return nil
}

func caller() {
  // 是否可能在此处检索到callee返回的行号?
  callee()
}

我认为这是不可能的,因为它应该已经从堆栈中移除了,但也许它仍然被缓存在某个地方?

使用案例是我有一个HTTP处理程序,我想记录返回错误的行号和文件名,而不必在代码中添加大量的代码。

英文:

Is it possible to get the line number on which a function returned from the calling scope?

Example:

func callee() error {
  if cond {
    return errors.New("whoops!")
  }
  return nil
}

func caller() {
  // Possible to retrieve the line number of callee return here?
  callee()
}

I assume that's not possible, since it should be already removed from the stack, but maybe it's still cached somewhere?

The use case is that I have a HTTP handler and I'd like to log the line and filename on which the error was returned, without having to litter the code.

答案1

得分: 7

AFAIK,不可能自动获取执行最后一个返回的行。

但是,通过一个小的辅助函数可以实现:

package main

import (
    "fmt"
    "runtime"
)

func here(s string, args ...interface{}) error {
    _, fname, fline, _ := runtime.Caller(1)
    h := fmt.Sprintf("%s:%d: ", fname, fline)
    return fmt.Errorf(h+s, args...)
}

func foo(i int) error {
    if i == 2 {
        return here("无法处理 %d", i) // line 16
    }

    if i%3 == 0 {
        return here("也无法处理 %d", i) // line 20
    }

    return nil
}

func main() {
    fmt.Println(foo(2))
    fmt.Println(foo(3))
    fmt.Println(foo(4))
}

输出:

/tmpfs/gosandbox-92c2a0f2_32bdf9d9_3c7d2a0a_80ba8510_f68d9721/prog.go:16: 无法处理 2
/tmpfs/gosandbox-92c2a0f2_32bdf9d9_3c7d2a0a_80ba8510_f68d9721/prog.go:20: 也无法处理 3
<nil>
英文:

AFAIK, it is not possible to automatically acquire the line where the last return was executed.

However, with a small helper one can have:

package main

import (
        &quot;fmt&quot;
        &quot;runtime&quot;
)

func here(s string, args ...interface{}) error {
        _, fname, fline, _ := runtime.Caller(1)
        h := fmt.Sprintf(&quot;%s:%d: &quot;, fname, fline)
        return fmt.Errorf(h+s, args...)
}

func foo(i int) error {
        if i == 2 {
                return here(&quot;cannot handle %d&quot;, i) // line 16
        }

        if i%3 == 0 {
                return here(&quot;also cannot handle %d&quot;, i) // line 20
        }

        return nil
}

func main() {
        fmt.Println(foo(2))
        fmt.Println(foo(3))
        fmt.Println(foo(4))
}

Playground


Output:

/tmpfs/gosandbox-92c2a0f2_32bdf9d9_3c7d2a0a_80ba8510_f68d9721/prog.go:16: cannot handle 2
/tmpfs/gosandbox-92c2a0f2_32bdf9d9_3c7d2a0a_80ba8510_f68d9721/prog.go:20: also cannot handle 3
&lt;nil&gt;

huangapple
  • 本文由 发表于 2013年7月9日 16:32:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/17543546.html
匿名

发表评论

匿名网友

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

确定