当golang业务模块发生异常的时候,我们常常需要获取其调用栈来确定发生异常的位置。这里来看看golang系统包中的net/http包(基于1.9版本)中是如何获取goroutine的调用栈的。其源代码如下:
// Serve a new connection.
func (c *conn) serve(ctx context.Context) {
c.remoteAddr = c.rwc.RemoteAddr().String()
ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())
defer func() {
if err := recover(); err != nil && err != ErrAbortHandler {
const size = 64 << 10
buf := make([]byte, size)
buf = buf[:runtime.Stack(buf, false)]
c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
}
if !c.hijacked() {
c.close()
c.setState(c.rwc, StateClosed)
}
}()
...
}
可以看出,获取goroutine调用栈的正确状态为:
const size = 64 << 10
buf := make([]byte, size)
buf = buf[:runtime.Stack(buf, false)]
buf中存放的就是当前goroutine的调用栈。如果想获取所有goroutine的调用栈,那么把runtime.Stack方法中第二个参数改为true即可。
推荐在所有的接口处都要加上异常处理,并且将调用栈存储起来。虽然可能会稍微牺牲一点点性能。但是服务最重要的参数是业务的正确性和可靠性,在这个基础上再追求高性能。
版权声明:本文为m0_38132420原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。