用golang系统包中的处理方法获取goroutine的调用栈

当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版权协议,转载请附上原文出处链接和本声明。