首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将恢复传递到上goroutine golang

将恢复传递到上goroutine golang
EN

Stack Overflow用户
提问于 2015-04-05 21:36:17
回答 2查看 6.3K关注 0票数 4

我创建了一个并发运行函数的示例,在该示例中,我执行了异常处理和恢复:

代码语言:javascript
复制
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")
}

它给出了输出:

代码语言:javascript
复制
internal goroutine panicked: NOT main goroutine
hello world

有没有可能将我的代码从“内部”修改为“主”?换句话说,我想让它写到控制台上:

代码语言:javascript
复制
internal goroutine paniced: NOT main goroutine
main goroutine paniced: main
hello world

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

Playground

更新

我试着遵循@Momer的建议,通过通道发送一个错误,并在主goroutine中处理它,而不是试图制造恐慌:

代码语言:javascript
复制
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")
}

它会给出错误

代码语言:javascript
复制
all goroutines are asleep - deadlock

完整输出:

代码语言:javascript
复制
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

Update playground

EN

回答 2

Stack Overflow用户

发布于 2016-01-21 17:57:46

我把golang中的panic/recover看作是java或c++中的try/catch/final块。

有关更多详细信息,请访问Handling panics (from Golang spec)

因此,您可以将异常传递给方法的调用者。下面是一个简单的代码,希望它能有所帮助

注意:在函数Foo()中,我使用recover()来捕获错误,然后重新引发恐慌,以便稍后在外部调用者中捕获它。

代码语言:javascript
复制
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-------------")
}
票数 2
EN

Stack Overflow用户

发布于 2015-04-06 22:31:10

在您更新的问题中,一个线程通过从chanStr读取数据而被阻塞,而另一个线程通过向chanErr写入数据而被阻塞。改变写入顺序应该可以解决死锁问题。

代码语言:javascript
复制
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")
        }
        chanStr <- ""
        chanErr <- err
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29457856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档