检查函数是否被称为goroutine [英] Check if function is being called as goroutine or not

查看:63
本文介绍了检查函数是否被称为goroutine的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法找出正在运行的函数是否被称为goroutine?

Is there any way to find out if a running function was called as goroutine or not?

我已经读过"go tour",并且我对使用golang构建Websocket服务器感兴趣,因此我找到了本教程 https://tutorialedge.net/golang/go-websocket-tutorial/

I've read 'go tour' and I am interested in building a websocket server with golang, so I found this tutorial https://tutorialedge.net/golang/go-websocket-tutorial/

现在我想知道本教程中的wsEndpoint函数是否作为goroutine调用(例如go wsEndpoint(...)).

Now I'm wondering if wsEndpoint function from the tutorial is invoked as goroutine (e.g. go wsEndpoint(...)) or not.

我试图阅读http软件包文档,但是并没有清晰的图片,只是猜测处理程序将通过go例程调用.是真的吗?

I've tried to read http package documentation, but did not get clear picture, just a guess that the handler will be called with go routine. Is that true?

推荐答案

每个函数都从goroutine中调用,甚至是 main()函数(称为 main > goroutine).

Every function is called from a goroutine, even the main() function (which is called the main goroutine).

Go中的goroutines没有身份.哪个goroutine调用函数都没有关系.

And goroutines in Go have no identity. It does not matter which goroutine calls a function.

要回答您的原始"问题:

To answer your "original" question:

有没有办法找出正在运行的函数是否被称为goroutine?

Is there any way to find out if a running function was called as goroutine or not?

如果我们将其定义为使用 go 语句调用的函数,或者不使用该语句,则答案是肯定的:我们可以进行检查.

If we define this as the function being called with the go statement or without that, then the answer is yes: we can check that.

但是在我们这样做之前:我不会将此信息用于任何用途.不要编写依赖于此的代码,也不要编写依赖于goroutine调用函数的代码.如果需要从多个goroutine并发访问资源,只需使用适当的同步即可.

But before we do: I would not use this information for anything. Don't write code that depends on this, nor on which goroutine calls a function. If you need to access a resource concurrently from multiple goroutines, just use proper synchronization.

基本上,我们可以检查调用堆栈:相互调用的函数的列表.如果该函数位于该列表的顶部,则使用 go 进行调用(请在答案末尾选中注释).如果在调用栈中还有其他函数,那么将在另一个函数中将它不带 go 调用(放在调用栈中的前面).

Basically we can check the call stack: the list of functions that call each other. If the function is at the top of that list, then it was called using go (check note at the end of the answer). If there are other functions before that in the call stack, then it was called without go, from another function (that places before in the call stack).

我们可能使用 runtime.Callers() 来获取调用goroutine的堆栈.这是我们可以检查是否还有其他函数调用"us"的方法:

We may use runtime.Callers() to get the calling goroutine's stack. This is how we can check if there are other functions calling "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) }

这将输出(在转到游乐场上尝试):

This will output (try it on the 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()).您可以在此转到游乐场中查看包含函数和文件名+行号的完整调用堆栈.这并不会改变该解决方案的可行性,只是我们必须跳过3帧而不是2帧,才能知道是从另一个函数中调用 f()还是使用 go 语句.

Note: basically there is a runtime.goexit() function on "top" of all call stacks, this is the top-most function running on a goroutine and is the "exit" point for all goroutines. This is why we skip 3 frames from the stack (0. is runtime.Callers() itself, 1. is the f() function, and the last one to skip is runtime.goexit()). You can check the full call stacks with function and file names+line numbers in this Go Playground. This doesn't change the viability of this solution, it's just that we have to skip 3 frames instead of 2 to tell if f() was called from another function or with the go statement.

这篇关于检查函数是否被称为goroutine的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆