github.com/zach-klippenstein/go@v0.0.0-20150108044943-fcfbeb3adf58/test/recover1.go (about) 1 // run 2 3 // Copyright 2010 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 // Test of recover during recursive panics. 8 // Here be dragons. 9 10 package main 11 12 import "runtime" 13 14 func main() { 15 test1() 16 test2() 17 test3() 18 test4() 19 test5() 20 test6() 21 test7() 22 } 23 24 func die() { 25 runtime.Breakpoint() // can't depend on panic 26 } 27 28 func mustRecover(x interface{}) { 29 mustNotRecover() // because it's not a defer call 30 v := recover() 31 if v == nil { 32 println("missing recover") 33 die() // panic is useless here 34 } 35 if v != x { 36 println("wrong value", v, x) 37 die() 38 } 39 40 // the value should be gone now regardless 41 v = recover() 42 if v != nil { 43 println("recover didn't recover") 44 die() 45 } 46 } 47 48 func mustNotRecover() { 49 v := recover() 50 if v != nil { 51 println("spurious recover") 52 die() 53 } 54 } 55 56 func withoutRecover() { 57 mustNotRecover() // because it's a sub-call 58 } 59 60 func test1() { 61 // Easy nested recursive panic. 62 defer mustRecover(1) 63 defer func() { 64 defer mustRecover(2) 65 panic(2) 66 }() 67 panic(1) 68 } 69 70 func test2() { 71 // Sequential panic. 72 defer mustNotRecover() 73 defer func() { 74 v := recover() 75 if v == nil || v.(int) != 2 { 76 println("wrong value", v, 2) 77 die() 78 } 79 defer mustRecover(3) 80 panic(3) 81 }() 82 panic(2) 83 } 84 85 func test3() { 86 // Sequential panic - like test2 but less picky. 87 defer mustNotRecover() 88 defer func() { 89 recover() 90 defer mustRecover(3) 91 panic(3) 92 }() 93 panic(2) 94 } 95 96 func test4() { 97 // Single panic. 98 defer mustNotRecover() 99 defer func() { 100 recover() 101 }() 102 panic(4) 103 } 104 105 func test5() { 106 // Single panic but recover called via defer 107 defer mustNotRecover() 108 defer func() { 109 defer recover() 110 }() 111 panic(5) 112 } 113 114 func test6() { 115 // Sequential panic. 116 // Like test3, but changed recover to defer (same change as test4 → test5). 117 defer mustNotRecover() 118 defer func() { 119 defer recover() // like a normal call from this func; runs because mustRecover stops the panic 120 defer mustRecover(3) 121 panic(3) 122 }() 123 panic(2) 124 } 125 126 func test7() { 127 // Like test6, but swapped defer order. 128 // The recover in "defer recover()" is now a no-op, 129 // because it runs called from panic, not from the func, 130 // and therefore cannot see the panic of 2. 131 // (Alternately, it cannot see the panic of 2 because 132 // there is an active panic of 3. And it cannot see the 133 // panic of 3 because it is at the wrong level (too high on the stack).) 134 defer mustRecover(2) 135 defer func() { 136 defer mustRecover(3) 137 defer recover() // now a no-op, unlike in test6. 138 panic(3) 139 }() 140 panic(2) 141 }