testing.M在golang中恢复

This recovery works:

func TestSomeTest(t *testing.T) {
    defer func() {
        r := recover()
        fmt.Println("recovery")
        fmt.Println(r)
    }()
    panic("panic here")
}

But this does not:

func TestSomeTest(t *testing.T) {
    panic("panic here")
}

func TestMain(m *testing.M) {
    defer func() {
        r := recover()
        fmt.Println("recovery")
        fmt.Println(r)
    }()
    ret := m.Run()
    os.Exit(ret)
}

Why? I expect that panic here will be recovered by code in func TestMain(m *testing.M). Why not? I just have panic without any recovery in this case.

Full code:

package main

import (
    "fmt"
    "os"
    "testing"
)

func TestSomeTest(t *testing.T) {
    // defer func() {
    //  r := recover()
    //  fmt.Println("recovery")
    //  fmt.Println(r)
    // }()
    panic("panic here")
}

func TestMain(m *testing.M) {
    defer func() {
        r := recover()
        fmt.Println("recovery")
        fmt.Println(r)
    }()
    ret := m.Run()
    os.Exit(ret)
}

To run this code I used go test command.

It's because the tests are run in separate goroutines.

It's like if your fist example sent off a goroutine, which can't be recovered.

func TestSomeTest(t *testing.T) {
    defer func() {
        r := recover()
        fmt.Println("recovery")
        fmt.Println(r)
    }()

    go func() {
        // won't recover
        panic("panic here")
    }()
    time.Sleep(time.Second)
}