如何解释Go stacktrace

时间:2016-04-06 18:47:14

标签: go

我在运行go程序时得到这个堆栈跟踪:

        /home/travis/.gimme/versions/go1.6.linux.amd64/src/runtime/panic.go:464 +0x3e6
github.com/DataDog/datadog-go/statsd.(*Client).Event(0x0, 0xc8200c7ec8, 0x0, 0x0)
        /home/travis/gopath/src/github.com/DataDog/datadog-go/statsd/statsd.go:286 +0x11f
github.com/some/path/server.(*Server).buildAndUpdate(0xc820024068, 0xc820064600, 0x0, 0x0)
        /home/travis/gopath/src/github.com/some/path/server/http.go:86 +0xf9f
created by github.com/some/path/server.(*Server).processPullRequestEvent
        /home/travis/gopath/src/github.com/some/path/server/http.go:169 +0x53f

Event函数的签名是:

func (c *Client) Event(e *Event) error

也可以在这里看到:https://github.com/DataDog/datadog-go/blob/cc2f4770f4d61871e19bfee967bc767fe730b0d9/statsd/statsd.go#L285

Event的类型定义可以在这里看到:https://github.com/DataDog/datadog-go/blob/cc2f4770f4d61871e19bfee967bc767fe730b0d9/statsd/statsd.go#L333

Client的类型定义可以在这里看到:https://github.com/DataDog/datadog-go/blob/cc2f4770f4d61871e19bfee967bc767fe730b0d9/statsd/statsd.go#L59

我的问题是,我如何解释这一行的内存地址,更一般地说,任何涉及类型变量作为目标和参数的堆栈跟踪?

github.com/DataDog/datadog-go/statsd.(*Client).Event(0x0, 0xc8200c7ec8, 0x0, 0x0)

当我查看http://www.goinggo.net/2015/01/stack-traces-in-go.html(这是我能够在该主题上找到的唯一信息)时,我没有看到有关如何在涉及结构时解释输出的任何信息。

3 个答案:

答案 0 :(得分:10)

感谢@twotwotwo的评论,我想我想出来了。

在这一行

github.com/DataDog/datadog-go/statsd.(*Client).Event(0x0, 0xc8200c7ec8, 0x0, 0x0)
  • 第一个0x0*Client,确实是零。
  • 0xc8200c7ec8*Event
  • 以下0x0, 0x0表示类型error的返回值。根据{{​​3}},error是一个界面。根据{{​​3}},接口存储为两个指针。第一个指针指向存储在接口中的类型信息,第二个指针指向存储在接口中的数据。

我编写了以下程序来向自己演示不同的函数签名如何出现在堆栈跟踪中:

package main

import "errors"

type X struct {
        i int
}

type Y struct {
}

func (y *Y) foo(x *X) {
        panic("panic in foo")
}

func (y *Y) bar(x *X) (*Y) {
        panic("panic in bar")
        return y
}

func (y *Y) baz(x *X) (error) {
        panic("panic in baz")
        return errors.New("error in baz")
}

func (y *Y) bam() {
        panic("panic in bam")
}

func main() {
        y := new(Y)
        x := new(X)
        // comment out the ones you don't want to check
        y.foo(x)
        y.bar(x)
        y.baz(x)
        y.bam()
}

调用bam时,*Y作用于main.(*Y).bam(0xc82002df48) 但没有参数或返回值,输出包含:

foo

调用*Y时,*X作用于main.(*Y).foo(0xc820033f30, 0xc820033f30) 并以bar作为参数,但没有返回值,输出包含:

*Y

当调用*X时,*Y采用main.(*Y).bar(0xc820033f30, 0xc820033f30, 0x40fb46) 作为参数,并返回baz,输出包含:

*Y

调用*Xerror作为参数,main.(*Y).baz(0xc820033f38, 0xc820033f38, 0x0, 0x0) 作为参数,并返回def startLoading(): p, songs = loadSongs() (这是一个接口),输出包含:< / p>

<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <LINK href="stylesheet.css" rel="stylesheet" type="text/css">
</head>
<body>
    <div id="mainpanel" class="notselectable">
        <div id="top">
            <img src="icons/white/open.png" style="float:right" class="btnMedia" />
        </div>
        <div id="bottom">
            <center>
                <img src="icons/white/pre.png" class="leftandright btnMedia" />
                <img src="icons/white/play.png" class="leftandright btnMedia" />
                <img src="icons/white/next.png" class="leftandright btnMedia" />
            </center>
        </div>
    </div>
</body>
<script>
    var panel = document.getElementById("mainpanel");
    var top = document.getElementById("top");
    var bottom = document.getElementById("bottom");
    //alert("script")
    panel.onmouseover = function() {
        alert("in")
        top.display = "block";
        bottom.display = "block";
    }
    panel.onmouseout = function() {
        alert("out")
        top.display = "none";
        bottom.display = "none";
    }
</script>
</html>

答案 1 :(得分:2)

你所拥有的是一个零指针取消引用。 (除非你使用的包unsafe,你可能不应该触及,所以我假设你不是。)

e调用时,func (c *Client) Event(e *Event) error的{​​{1}}参数似乎为nil

答案 2 :(得分:0)

基本上:方法接收器(如果有)、显式参数(如果有)、返回值(如果有)。

要了解堆栈跟踪,您首先需要了解 Go 的数据结构的内部表示。例如,切片类型的参数具有三个组件,因此在 func 的堆栈跟踪中包含三个值:data(a pointer), len(an int), cap(an int)。

您可能会发现 this article 很有用。