Раньше при зависшем тесте рука сама тянулась расставить fmt.Println и запустить заново. Сейчас делаю иначе. Ставлю короткий таймаут, и когда он истекает, пакет testing паникует и печатает стеки всех горутин.
package hang
import "testing"
func TestHandoff(t *testing.T) {
results := make(chan int)
go func() {
results <- 42 // nobody reads this
}()
done := make(chan struct{})
<-done
}
go test -timeout 3s выдаёт panic: test timed out after 3s, список запущенных тестов и потом горутины по одной. У каждой в квадратных скобках причина ожидания и строка, на которой она стоит. Здесь две нужные видно сразу. Одна в [chan receive] на строке с <-done, другая в [chan send] на results <- 42, и под ней строка created by, то есть кто её запустил. Ещё там пишется, сколько каждая горутина уже ждёт, так что старую утечку легко отличить от свежей.
Не знаю, почему print так долго меня устраивал. Наверное, потому что таймаут по умолчанию десять минут, и до дампа просто никто не дожидался.