有没有办法找出正在运行的函数是否被称为goroutine?
我已经读过“ go tour”,并且我对使用golang构建websocket服务器感兴趣,因此我找到了本教程https://tutorialedge.net/golang/go-websocket-tutorial/
现在我想知道教程中的wsEndpoint函数是否作为goroutine调用(例如go wsEndpoint(...))。
我试图阅读http软件包文档,但是并没有清晰的图片,只是猜测处理程序将通过go例程调用。是真的吗?
答案 0 :(得分:3)
每个函数都从goroutine中调用,甚至是main()
函数(也称为main
goroutine)。
Go中的goroutines没有身份。哪个goroutine调用函数都没有关系。
回答您的“原始”问题:
有没有办法找出正在运行的函数是否被称为goroutine?
如果将其定义为使用go
语句调用的函数,或者不使用该语句,则答案是肯定的:我们可以进行检查。
但是在我们这样做之前:我不会将这些信息用于任何事情。不要编写依赖于此的代码,也不要编写依赖于goroutine调用函数的代码。如果您需要同时从多个goroutine访问资源,请使用适当的同步。
基本上,我们可以检查调用堆栈:相互调用的函数的列表。如果该函数在该列表的顶部,则使用go
进行调用(请在答案末尾注明)。如果调用栈中的该函数之前还有其他函数,则在不使用go
的情况下从另一个函数(在调用栈中的该函数之前)进行调用。
我们可以使用runtime.Callers()
来获取调用goroutine的堆栈。这是我们如何检查是否还有其他函数调用“ us”:
func f(name string) {
count := runtime.Callers(3, make([]uintptr, 1))
if count == 0 {
fmt.Printf("%q is launched as new\n", name)
}
}
测试:
func main() {
f("normal")
go f("with-go")
func() { f("from-anon") }()
func() { go f("from-anon-with-go") }()
f2("from-f2")
go f2("with-go-from-f2")
f3("from-f3")
go f3("with-go-from-f3")
time.Sleep(time.Second)
}
func f2(name string) { f(name) }
func f3(name string) { go f(name) }
这将输出(在Go Playground上尝试):
"with-go" is launched as new
"from-anon-with-go" is launched as new
"from-f3" is launched as new
"with-go-from-f3" is launched as new
注意:基本上,所有调用堆栈的“顶部”都有一个runtime.goexit()
函数,这是在goroutine上运行的最顶层函数,并且是所有goroutine的“退出”点。这就是为什么我们从堆栈中跳过3帧的原因(0是runtime.Callers()
本身,1.是f()
函数,最后一个要跳过的帧是runtime.goexit()
)。您可以在此Go Playground中查看包含函数和文件名+行号的完整调用堆栈。但这并不会改变该解决方案的可行性,只是我们必须跳过3帧而不是2帧才能知道是从另一个函数还是通过f()
语句调用了go
。