我在运行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
Run Code Online (Sandbox Code Playgroud)
Event函数的签名是:
func (c *Client) Event(e *Event) error
Run Code Online (Sandbox Code Playgroud)
这也可以在这里看到: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)
Run Code Online (Sandbox Code Playgroud)
当我查看http://www.goinggo.net/2015/01/stack-traces-in-go.html(这是我能够在这个主题上找到的唯一信息)时,我没有看到任何关于如何在涉及结构时解释输出.
des*_*ons 13
感谢@twotwotwo的评论,我想我想出来了.
在这一行
github.com/DataDog/datadog-go/statsd.(*Client).Event(0x0, 0xc8200c7ec8, 0x0, 0x0)
Run Code Online (Sandbox Code Playgroud)
0x0是*Client,这确实是零.0xc8200c7ec8 是 *Event0x0, 0x0代表类型的返回值error.error根据http://blog.golang.org/error-handling-and-go,是一个界面.根据http://research.swtch.com/interfaces,接口存储为两个指针.第一个指针指向存储在接口中的类型信息,第二个指针指向存储在接口中的数据.我编写了以下程序来向自己演示不同的函数签名如何出现在堆栈跟踪中:
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()
}
Run Code Online (Sandbox Code Playgroud)
当bam被调用时,作用于*Y,但没有参数和返回值,输出包含:
main.(*Y).bam(0xc82002df48)
Run Code Online (Sandbox Code Playgroud)
当foo被调用时,作用于*Y和需要*X作为参数,但没有返回值,输出包含:
main.(*Y).foo(0xc820033f30, 0xc820033f30)
Run Code Online (Sandbox Code Playgroud)
当bar被调用时,它作用于*Y,需要一个*X作为参数,并返回一个*Y,输出包含:
main.(*Y).bar(0xc820033f30, 0xc820033f30, 0x40fb46)
Run Code Online (Sandbox Code Playgroud)
当baz被调用时,它作用于*Y,取*X作为参数,并返回一个error(它是一个接口),输出包含:
main.(*Y).baz(0xc820033f38, 0xc820033f38, 0x0, 0x0)
Run Code Online (Sandbox Code Playgroud)