检查函数是否被称为goroutine

时间:2019-06-21 11:03:11

标签: go goroutine

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

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

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

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

1 个答案:

答案 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

相关问题