Go例程和Defer

Go routines and Defer

func main() {
    defer fmt.Println("Main defer")
    go t1()
    go t2()
    go t3()
    time.Sleep(20 * time.Second)

}

func t1() {
    defer fmt.Println("t1 defer")
    time.Sleep(20 * time.Second)
}
func t2() {
    defer fmt.Println("t2 defer")
    time.Sleep(5 * time.Second)
    panic(New("T2"))
}
func t3() {
    defer fmt.Println("t3 defer")
    time.Sleep(20 * time.Second)
}

1 个线程 (t2) 调用 panic,调用 t2 defer。 当 t2 发生恐慌时,其他所有线程也将终止。 我希望调用每个线程的延迟。 这是一种必须出现恐慌的情况,恐慌发生在一个线程中。所以我希望每个线程都知道程序将要退出。 有什么方法可以实现吗?

当前输出:

t2 defer
panic: T2

goroutine 19 [running]:
main.t2()
        C:/Users/Talha.Irfan/OneDrive - Bentley Systems, Inc/Desktop/go_test/src/main2/main.go:34 +0x105
created by main.main
        C:/Users/Talha.Irfan/OneDrive - Bentley Systems, Inc/Desktop/go_test/src/main2/main.go:21 +0xb0

代码崩溃后不会调用任何内容。这就是 panic 的工作原理,你的程序将在 panic 之后存在。如果发生恐慌,您可以使用通道将值发送到其他 go 例程。还有一件事,最好使用 Wait Groups 等待所有 go 例程完成而不是使用 time.Sleep.

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    defer fmt.Println("Main defer")
    ch := make(chan int)
    wg.Add(1)
    go t1(ch, &wg)
    wg.Add(1)
    go t2(ch, &wg)
    wg.Add(1)
    go t3(ch, &wg)
    ch <- 1
    close(ch)
    wg.Wait()
}

func t1(ch chan int, wg *sync.WaitGroup) {
    defer fmt.Println("t1 defer")
    defer wg.Done()
}

func t2(ch chan int,wg *sync.WaitGroup) {
    defer fmt.Println("t2 defer")
    for {
         foo, ok := <- ch
         if !ok {
                println("done")
                wg.Done()
                return
         }
         println(foo)
    }
}
func t3(ch chan int, wg *sync.WaitGroup) {
    defer fmt.Println("t3 defer")
    defer wg.Done()
}

Playground Example

如果您在代码中遇到错误,您可以使用 recover 来捕获错误。这将导致您的代码 运行 所有 goroutines。

package main

import (
    "fmt"
    "time"
)

func main() {
    defer fmt.Println("Main defer")
    go t1()
    go t2()
    go t3()
    time.Sleep(2 * time.Second)

}

func t1() {
    defer fmt.Println("t1 defer")
}
func t2() {
    defer fmt.Println("t2 defer")
        defer func() {
            if r := recover(); r != nil {
                println("panic:" + r.(string))
            }
        }()
}
func t3() {
    defer fmt.Println("t3 defer")
}

Go playground

上的工作代码