我想知道从golang函数退出时的返回值。 golang延迟机制很有用,但它会在注册延迟语句时而不是在执行延迟语句时评估参数。 我可以使用匿名函数来访问返回值:
1 2 3 4 5 6 7 8 9 | func try() (int i) { defer func() {fmt.Printf("%d", i)}() i = 10 return i+1 } func main() { try() } |
我认为这可以正常工作,但是我想以一种通用的方式来处理,也许是这样的:
1 2 3 | func try(in string) (out int) { enter("%s", in);exit("%d", out) } |
或者甚至更好的是,在进入/退出时使用反射来输出自变量/返回值。 我假设运行时性能并不重要:)。
有什么好方法吗? Shaba Abhiram方便的Tracey库确实朝着这个方向走了很长一段路,但是没有打印返回值。
- 您打算将其用于什么?
- 你什么意思? 它的通用。
- c#:链接的等效问题。 他们正在使用运行时。 也许有一种方法可以使用Go运行时来生成跟踪输出,而无需程序员进行任何检测。
- 即使它是通用的,您仍然打算将其用于某些用途。 每机会调试一次吗?
- 我的迫切需求只是离线调试/健全性检查。
- 也许对某些人感兴趣:最佳日志记录
在评估延迟函数的参数是在延迟排队的点而不是在执行延迟的时刻进行评估是正确的。
您制作引用命名返回的匿名函数的方法有效。 另一种方法是传递返回值的地址:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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) } } |
这种方法的问题在于,您的日志记录函数现在具有指针而不是实际类型,并且必须解开指针才能对其执行任何操作。 但是,如果您使用的是
- 谢谢captn。我开始认为应该有一种方法可以通过调试级别的函数进入/退出钩子来实现。我不认为go运行时会暴露所需的钩子,但可能是错误的。我怀疑您可以在GDB中检索跟踪信息,而无需深入研究golang细节。 Golang具有c的基础,并且那里有很多现有的,相对快速的,不引人注目的工具。
- @DavidAiken我认为很多工具都通过生成插入调试代码的代码来执行此类操作。
- 我认为不利之处在于,通常客户拥有非调试版本,而调试版本对于heisenbug而言太慢。理想情况下,您将能够使他们使用当前版本来创建日志,以帮助您进行故障排除,甚至重现环境中的问题。我认为Go运行时具有数据。可能有一个选项可以启用不同详细程度的跟踪日志记录,而不会在正常操作期间产生高昂的成本。这样的选项将避免在应用程序中使用自定义检测代码,并且可以使用标准工具来处理日志。
- @DavidAiken我将这种方法更多地用于运行时检测而非调试。诸如指标/日志记录等之类的东西。如果要调试,请使用调试器。 Printfs为我提供了我所需的大部分东西。
- 谢谢captn ..我在优胜美地(Yosemite)上,我现在只对LLVM感兴趣,但是我稍后可能会再来。针对不同人的不同笔触..这里有一些c宏,用于捕获嵌套函数的进入/退出跟踪。在运行时中使用反射数据的快速工具在现场支持生产代码时也可能会有帮助,但这仅是一个意见。
在不添加大量
- 谢谢你它是对工具集的不错补充。在DWARF级别上还有一些选项。似乎可以使用内置Go支持的GCC 4.8+版本之一。最近还有一个clang端口。
- 请注意,尽管这是很有前途的东西,但目前还很不成熟。我能够从中获得一些有趣的见解,但是安装也杀死了我gopath中的依赖项。请勿在生产gopath中使用(尚未使用)。
- 是的,我的经验也是如此。如您所知,OSX最近放弃了GCC取而代之的是LLVM,而自制软件在优胜美地上全新安装GCC 4.9时遇到了问题。就目前而言,香港专业教育学院只是略微修改了Tracey库以打印输出值。.我没有很多要监视的调用。我认为go运行时具有足够的元数据来执行自动跟踪,但是我认为没有公开必要的接口。如果有标准接口可用,则在事件源中也可能有用。