Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 上戈罗廷戈朗传球恢复_Go - Fatal编程技术网

Go 上戈罗廷戈朗传球恢复

Go 上戈罗廷戈朗传球恢复,go,Go,我创建了一个示例,在该示例中,我同时运行函数,并在其中死机和恢复: package main import "fmt" func main() { // "main" recovery defer func() { if r := recover(); r != nil { fmt.Println("main goroutine paniced:", r) }

我创建了一个示例,在该示例中,我同时运行函数,并在其中死机和恢复:

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")
}
是否可以将我的代码更改为使pass恢复从“internal”变为“main”?换句话说,我希望它写下来到控制台:

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")
}
全输出:

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

在您更新的问题中,一个线程通过读取
chanStr
被阻止,而另一个线程通过写入
chanErr
被阻止。 切换写入顺序应该可以解决死锁

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
    }
}
defer func(){
如果r:=recover();r!=nil{
fmt.Println(“内部goroutine恐慌:”,r)
开关t:=r(类型){
大小写字符串:
fmt.Println(“err是字符串”)
err=错误。新建(t)
案例错误:
fmt.Println(“错误即错误”)
err=t
违约:
fmt.Println(“错误未知”)
err=错误。新建(“未知错误”)
}

在Gangon中,我尝试了java/C++中的尝试/抓取/最终块。 有关更多详细信息,请访问

所以您可以向方法的调用方传递一个panic。 下面是一个简单的代码,希望对您有所帮助

注意:在函数Foo()中,我使用recover()捕捉出错的情况,然后重新惊慌,以便稍后在外部调用程序中捕捉它

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-------------")
}

与其试图让恐慌爆发,为什么不通过通道发送一个错误并在主goroutine中处理它呢?@Momer我已经尝试过了,但出现了错误
所有goroutine都处于休眠状态-死锁
,请查看我上面的更新。第二次写入(在您的恢复中)块,因为没有人从通道中读取。您要多次写入通道,但只读取一次。@flx为什么要写入多次?我在
chanErr
中写入一次,在第二个恢复块
chanStr
中写入一次:
chanErr
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
    }
}
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-------------")
}