当前位置: 首页 > 知识库问答 >
问题:

将恢复传递到上goroutine golang

岑和风
2023-03-14
package main

import "fmt"

func main() {
    // "main" recovery
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("main goroutine paniced:", r)
        }
    }()

    // running function concurrently inside which I panic
    chanStr := make(chan string)
    go func() {
        // this "internal" goroutin recovery
        defer func() {
            if r := recover(); r != nil {
                fmt.Println("internal goroutine paniced:", r)
            }
            chanStr <- "hello world"
        }()
        // panicking and wanting recovery not only in "internal" recovery but in "main" recovery as well
        panic("NOT main goroutine")
    }()
    // waiting for chan with "internal" goroutine panicking and recovery
    str := <-chanStr
    fmt.Println(str)

    // panic("main")
}
internal goroutine panicked: NOT main goroutine
hello world
internal goroutine paniced: NOT main goroutine
main goroutine paniced: main
hello world

我试图通过删除“内部”恢复func来实现这一点,但在这种情况下,“主”恢复不能恢复“内部”goroutine内部的恐慌。

操场

我试图听从@momer的建议,通过通道发送错误并在主goroutine中处理它,而不是试图制造恐慌:

package main

import (
    "errors"
    "fmt"
)

func main() {
    // "main" recovery
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("main goroutine paniced:", r)
        }
    }()

    // running func concarantly inside which I panic
    chanStr := make(chan string)
    chanErr := make(chan error)
    var err error
    go func() {
        // this "internal" goroutin recovery
        defer func() {
            if r := recover(); r != nil {
                fmt.Println("internal goroutine paniced:", r)
                switch t := r.(type) {
                case string:
                    fmt.Println("err is string")
                    err = errors.New(t)
                case error:
                    fmt.Println("err is error")
                    err = t
                default:
                    fmt.Println("err is unknown")
                    err = errors.New("Unknown error")
                }

                chanErr <- err
                chanStr <- ""
            }
        }()
        // panicing and wanting recovery not only in "internal" recovery but in "main" recovery as well
        panic("NOT main goroutine")
        chanStr <- "hello world"
        chanErr <- nil

    }()
    // waiting for chan with "internal" goroutin panicing and recovery
    str := <-chanStr
    err = <-chanErr
    fmt.Println(str)
    fmt.Println(err)

    // panic("main")
}
all goroutines are asleep - deadlock
go run /goPath/parentRecoverty2.go
internal goroutine paniced: NOT main goroutine
err is string
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
    /goPath/parentRecoverty2.go:48 +0x1d4

goroutine 5 [chan send]:
main.func·002()
    /goPath/parentRecoverty2.go:37 +0x407
main.func·003()
    /goPath/parentRecoverty2.go:42 +0x130
created by main.main
    /goPath/parentRecoverty2.go:46 +0x190
exit status 2

共有1个答案

谢涵煦
2023-03-14

我将golang中的panic/recover作为java或C++中的try/catch/final块。

有关更多细节,您可以访问处理恐慌(来自Golang spec)。

因此可以将panic传递给方法的调用方。下面是一个简单的代码,希望对你有帮助

package main

import (
    "fmt"
    "time"
)

func Foo() {
    defer func() {
        if x := recover(); x != nil {
            fmt.Printf("Runtime panic: %v \n", x)
            panic("Ah oh ... Panic in defer")
        }
    }()
    panic("Panic in Foo() !")
}

func Game() {
    defer func(){
        fmt.Println("Clean up in Game()")
    }()

    defer func() {
        if x := recover(); x != nil {
            fmt.Println("Catch recover panic !!! In Game()")
        }
    }()
    Foo()

}

func main() {

    defer func() {
        fmt.Println("Program Quit ... ")
    }()

    fmt.Println("-----------Split-------------")
    go Game()
    time.Sleep(1 * time.Millisecond)
    fmt.Println("-----------Split-------------")
}
 类似资料:
  • 有人能告诉我如何在dropwizard 1.2.6中实现可恢复的文件上传吗?因此,如果用户试图上传一个大文件(4-5 GB),如果出现网络故障或浏览器错误关闭,那么用户将能够从中断的地方恢复该过程。

  • 使用 fetch 方法来上传文件相当容易。 连接断开后如何恢复上传?这里没有对此的内建选项,但是我们有实现它的一些方式。 对于大文件(如果我们可能需要恢复),可恢复的上传应该带有上传进度提示。由于 fetch 不允许跟踪上传进度,我们将会使用 XMLHttpRequest。 不太实用的进度事件 要恢复上传,我们需要知道在连接断开前已经上传了多少。 我们有 xhr.upload.onprogress

  • 我正在测试Android的驱动器API,以便上传一个文件,该文件可以显示上传的进度,并能够在失败时恢复上传(文件大小>30 MB) 与以下问题:上传下载的大文件到谷歌驱动器给错误,上传进度监听器没有激发(谷歌驱动器API)我能够得到上传进度,他们提到那些是可恢复的上传。但是,我没有看到任何寻找上传错误和恢复逻辑的代码,因此,如果我杀死应用程序并“恢复”上传,它只是从头开始。

  • 在一个DOM操作练习中,我学习了如何使用纯JavaScript创建HTML元素。也就是像这样的东西: 我必须创建一个函数,允许用户将对象作为参数传入,以设置元素的属性。这个对象包含任意数量的键(属性)和值(属性值)。即属性可以是“src”,值可以是“image.jpg”。类似的东西。用户可以在调用函数时向此对象传递任意多的属性。 附带说明,对代码和JS都很新,请原谅我:P

  • 我正在尝试使用Gmail的可恢复选项将附件上传到电子邮件。文件参考:https://developers.google.com/gmail/api/guides/uploads#resumable. 目前,我可以用可恢复的URI发送电子邮件,但没有附件(使用邮递员)。文档没有提供非常清楚的请求应该是什么样子的例子,在搜索互联网后,似乎也没有很多例子。 我的要求分为两部分: > 正文是64位编码字符

  • 问题内容: 短 以下代码不能完全满足您的期望:https : //play.golang.org/p/sO4w4I_Lle 我以为我像往常一样弄乱了一些指针/引用的东西,但是我希望我的… …和… …以相同的方式运行(例如,更新作为第二个参数传递的引用)。 长 上面的示例是一个没有太多意义的最小复制器。这是为了使其能够在操场上工作。但是,一个不那么有意义的最小示例是: 想法是将YAML解组为(而不是