为了账号安全,请及时绑定邮箱和手机立即绑定

检查函数是否被作为 goroutine 调用

检查函数是否被作为 goroutine 调用

Go
慕村225694 2023-06-26 16:59:09
有什么方法可以查明正在运行的函数是否被调用为 goroutine 吗?现在我想知道wsEndpoint 函数是否作为 goroutine 调用(例如 go wsEndpoint(...))。我尝试阅读 http 包文档,但没有得到清晰的图片,只是猜测处理程序将用 go 例程调用。真的吗?
查看完整描述

1 回答

?
四季花海

TA贡献1811条经验 获得超5个赞

每个函数都是从 goroutine 调用的,甚至是main()函数(称为 goroutine main)。

Go 中的 goroutine 没有身份。哪个 goroutine 调用函数并不重要。

回答你的“原始”问题:

有什么方法可以查明正在运行的函数是否被调用为 goroutine 吗?

如果我们将 this 定义为使用该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语句调用。

查看完整回答
反对 回复 2023-06-26
  • 1 回答
  • 0 关注
  • 111 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信