[{"data":1,"prerenderedAt":857},["ShallowReactive",2],{"content:\u002F2025\u002F08\u002Fgo-panic":3,"surround:\u002F2025\u002F08\u002Fgo-panic":847},{"id":4,"title":5,"body":6,"categories":826,"date":828,"description":829,"draft":830,"extension":831,"image":832,"meta":833,"navigation":61,"path":835,"permalink":832,"published":832,"readingTime":836,"recommend":832,"references":832,"seo":841,"sitemap":842,"stem":843,"tags":844,"type":845,"updated":828,"__hash__":846},"content\u002Fposts\u002F2025\u002F08\u002Fgo-panic.md","Go Panic 与 Recover 异常处理",{"type":7,"value":8,"toc":824},"minimark",[9,19,30,33,226,229,237,240,243,246,350,353,368,371,686,688,810,813,820],[10,11,12,16],"ol",{},[13,14,15],"li",{},"panic 是 go 的内置机制，输出严重错误。如果没有恢复程序会打印堆栈，然后退出",[13,17,18],{},"recover 也是 go 的内置机制，在当前 goroutine 恢复 panic，返回值为 panic 中的引用信息",[20,21,22],"blockquote",{},[23,24,25,29],"p",{},[26,27,28],"strong",{},"注意："," recover 一定要与 defer 一起使用，不然 recover 只会返回 nil",[23,31,32],{},"示例程序：",[34,35,40],"pre",{"className":36,"code":37,"language":38,"meta":39,"style":39},"language-go shiki shiki-themes github-light github-dark","package main\n\nfunc A() {\n\tB()\n}\n\nfunc B() {\n\tC()\n}\n\nfunc C() {\n\tpanic(\"报错了\")\n}\n\nfunc main() {\n\tA()\n}\n","go","",[41,42,43,56,63,86,102,108,113,129,141,146,151,167,183,188,193,209,221],"code",{"__ignoreMap":39},[44,45,48,52],"span",{"class":46,"data-line":47,"line":47},"line",1,[44,49,51],{"class":50},"szBVR","package",[44,53,55],{"class":54},"sScJk"," main\n",[44,57,59],{"class":46,"data-line":58,"line":58},2,[44,60,62],{"emptyLinePlaceholder":61},true,"\n",[44,64,66,69,72,76,79,83],{"class":46,"data-line":65,"line":65},3,[44,67,68],{"class":50},"func",[44,70,71],{"class":54}," A",[44,73,75],{"class":74},"sSDpw","(",[44,77,78],{"class":74},")",[44,80,82],{"class":81},"sVt8B"," ",[44,84,85],{"class":74},"{\n",[44,87,89,93,96,99],{"class":46,"data-line":88,"line":88},4,[44,90,92],{"class":91},"indent","\t",[44,94,95],{"class":54},"B",[44,97,75],{"class":98},"sJX2D",[44,100,101],{"class":98},")\n",[44,103,105],{"class":46,"data-line":104,"line":104},5,[44,106,107],{"class":74},"}\n",[44,109,111],{"class":46,"data-line":110,"line":110},6,[44,112,62],{"emptyLinePlaceholder":61},[44,114,116,118,121,123,125,127],{"class":46,"data-line":115,"line":115},7,[44,117,68],{"class":50},[44,119,120],{"class":54}," B",[44,122,75],{"class":74},[44,124,78],{"class":74},[44,126,82],{"class":81},[44,128,85],{"class":74},[44,130,132,134,137,139],{"class":46,"data-line":131,"line":131},8,[44,133,92],{"class":91},[44,135,136],{"class":54},"C",[44,138,75],{"class":98},[44,140,101],{"class":98},[44,142,144],{"class":46,"data-line":143,"line":143},9,[44,145,107],{"class":74},[44,147,149],{"class":46,"data-line":148,"line":148},10,[44,150,62],{"emptyLinePlaceholder":61},[44,152,154,156,159,161,163,165],{"class":46,"data-line":153,"line":153},11,[44,155,68],{"class":50},[44,157,158],{"class":54}," C",[44,160,75],{"class":74},[44,162,78],{"class":74},[44,164,82],{"class":81},[44,166,85],{"class":74},[44,168,170,172,175,177,181],{"class":46,"data-line":169,"line":169},12,[44,171,92],{"class":91},[44,173,174],{"class":54},"panic",[44,176,75],{"class":98},[44,178,180],{"class":179},"sZZnC","\"报错了\"",[44,182,101],{"class":98},[44,184,186],{"class":46,"data-line":185,"line":185},13,[44,187,107],{"class":74},[44,189,191],{"class":46,"data-line":190,"line":190},14,[44,192,62],{"emptyLinePlaceholder":61},[44,194,196,198,201,203,205,207],{"class":46,"data-line":195,"line":195},15,[44,197,68],{"class":50},[44,199,200],{"class":54}," main",[44,202,75],{"class":74},[44,204,78],{"class":74},[44,206,82],{"class":81},[44,208,85],{"class":74},[44,210,212,214,217,219],{"class":46,"data-line":211,"line":211},16,[44,213,92],{"class":91},[44,215,216],{"class":54},"A",[44,218,75],{"class":98},[44,220,101],{"class":98},[44,222,224],{"class":46,"data-line":223,"line":223},17,[44,225,107],{"class":74},[23,227,228],{},"输出结果：",[34,230,235],{"className":231,"code":233,"language":234,"meta":39},[232],"language-text","panic: 报错了\n\ngoroutine 1 [running]:\nmain.C(...)\n        \u002Fcode\u002Fdemo\u002Fpanic\u002Fmain.go:12\nmain.B(...)\n        \u002Fcode\u002Fdemo\u002Fpanic\u002Fmain.go:8\nmain.A(...)\n        \u002Fcode\u002Fdemo\u002Fpanic\u002Fmain.go:4\nmain.main()\n        \u002Fcode\u002Fdemo\u002Fpanic\u002Fmain.go:16 +0x25\nexit status 2\n","text",[41,236,233],{"__ignoreMap":39},[23,238,239],{},"对应的报错堆栈信息比较清晰\nC -> B -> A -> main",[23,241,242],{},"最后抛到 main 函数",[23,244,245],{},"我们可以在 main 调用 A 函数前使用 defer+recover 对 panic 进行捕获",[34,247,249],{"className":36,"code":248,"language":38,"meta":39,"style":39},"defer func() {\n    if r := recover(); r != nil {\n        fmt.Println(\"捕获到异常\", r)\n    }\n}()\nA()\n",[41,250,251,267,302,325,333,342],{"__ignoreMap":39},[44,252,253,256,259,261,263,265],{"class":46,"data-line":47,"line":47},[44,254,255],{"class":50},"defer",[44,257,258],{"class":50}," func",[44,260,75],{"class":74},[44,262,78],{"class":74},[44,264,82],{"class":81},[44,266,85],{"class":74},[44,268,269,272,275,278,281,284,286,288,291,294,298,300],{"class":46,"data-line":58,"line":58},[44,270,271],{"class":91},"    ",[44,273,274],{"class":50},"if",[44,276,277],{"class":81}," r ",[44,279,280],{"class":50},":=",[44,282,283],{"class":54}," recover",[44,285,75],{"class":98},[44,287,78],{"class":98},[44,289,290],{"class":81},"; r ",[44,292,293],{"class":50},"!=",[44,295,297],{"class":296},"sj4cs"," nil",[44,299,82],{"class":81},[44,301,85],{"class":98},[44,303,304,306,308,311,314,317,320,323],{"class":46,"data-line":65,"line":65},[44,305,271],{"class":91},[44,307,271],{"class":91},[44,309,310],{"class":81},"fmt.",[44,312,313],{"class":54},"Println",[44,315,75],{"class":316},"sqkie",[44,318,319],{"class":179},"\"捕获到异常\"",[44,321,322],{"class":81},", r",[44,324,101],{"class":316},[44,326,327,329,331],{"class":46,"data-line":88,"line":88},[44,328,271],{"class":91},[44,330,39],{"class":81},[44,332,107],{"class":98},[44,334,335,338,340],{"class":46,"data-line":104,"line":104},[44,336,337],{"class":74},"}",[44,339,75],{"class":74},[44,341,101],{"class":74},[44,343,344,346,348],{"class":46,"data-line":110,"line":110},[44,345,216],{"class":54},[44,347,75],{"class":74},[44,349,101],{"class":74},[23,351,352],{},"如上述代码所示，这样就能成功捕获错误，输出如下",[34,354,358],{"className":355,"code":356,"language":357,"meta":39,"style":39},"language-bash shiki shiki-themes github-light github-dark","捕获到异常 报错了\n","bash",[41,359,360],{"__ignoreMap":39},[44,361,362,365],{"class":46,"data-line":47,"line":47},[44,363,364],{"class":54},"捕获到异常",[44,366,367],{"class":179}," 报错了\n",[23,369,370],{},"recover 只能用于当前 goroutine，我们来试试在子 goroutine 处 panic，main 函数是否能捕获到",[34,372,374],{"className":36,"code":373,"language":38,"meta":39,"style":39},"package main\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n)\n\nfunc doSomething() {\n\tdefer wg.Done()\n\tfmt.Println(\"准备panic\")\n\tpanic(\"子goroutine报错了\")\n}\n\nvar wg sync.WaitGroup\n\nfunc main() {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tfmt.Println(\"recover捕获到异常值为:\", r)\n\t\t}\n\t}()\n\twg.Add(1)\n\tgo doSomething()\n\twg.Wait()\n\tfmt.Println(\"无法捕获\")\n}\n",[41,375,376,382,386,396,409,420,424,428,443,459,474,487,491,495,511,515,529,545,574,596,607,620,638,651,665,681],{"__ignoreMap":39},[44,377,378,380],{"class":46,"data-line":47,"line":47},[44,379,51],{"class":50},[44,381,55],{"class":54},[44,383,384],{"class":46,"data-line":58,"line":58},[44,385,62],{"emptyLinePlaceholder":61},[44,387,388,391,393],{"class":46,"data-line":65,"line":65},[44,389,390],{"class":50},"import",[44,392,82],{"class":81},[44,394,395],{"class":74},"(\n",[44,397,398,400,403,406],{"class":46,"data-line":88,"line":88},[44,399,92],{"class":91},[44,401,402],{"class":179},"\"",[44,404,405],{"class":54},"fmt",[44,407,408],{"class":179},"\"\n",[44,410,411,413,415,418],{"class":46,"data-line":104,"line":104},[44,412,92],{"class":91},[44,414,402],{"class":179},[44,416,417],{"class":54},"sync",[44,419,408],{"class":179},[44,421,422],{"class":46,"data-line":110,"line":110},[44,423,101],{"class":74},[44,425,426],{"class":46,"data-line":115,"line":115},[44,427,62],{"emptyLinePlaceholder":61},[44,429,430,432,435,437,439,441],{"class":46,"data-line":131,"line":131},[44,431,68],{"class":50},[44,433,434],{"class":54}," doSomething",[44,436,75],{"class":74},[44,438,78],{"class":74},[44,440,82],{"class":81},[44,442,85],{"class":74},[44,444,445,447,449,452,455,457],{"class":46,"data-line":143,"line":143},[44,446,92],{"class":91},[44,448,255],{"class":50},[44,450,451],{"class":81}," wg.",[44,453,454],{"class":54},"Done",[44,456,75],{"class":98},[44,458,101],{"class":98},[44,460,461,463,465,467,469,472],{"class":46,"data-line":148,"line":148},[44,462,92],{"class":91},[44,464,310],{"class":81},[44,466,313],{"class":54},[44,468,75],{"class":98},[44,470,471],{"class":179},"\"准备panic\"",[44,473,101],{"class":98},[44,475,476,478,480,482,485],{"class":46,"data-line":153,"line":153},[44,477,92],{"class":91},[44,479,174],{"class":54},[44,481,75],{"class":98},[44,483,484],{"class":179},"\"子goroutine报错了\"",[44,486,101],{"class":98},[44,488,489],{"class":46,"data-line":169,"line":169},[44,490,107],{"class":74},[44,492,493],{"class":46,"data-line":185,"line":185},[44,494,62],{"emptyLinePlaceholder":61},[44,496,497,500,503,505,508],{"class":46,"data-line":190,"line":190},[44,498,499],{"class":50},"var",[44,501,502],{"class":81}," wg ",[44,504,417],{"class":54},[44,506,507],{"class":81},".",[44,509,510],{"class":54},"WaitGroup\n",[44,512,513],{"class":46,"data-line":195,"line":195},[44,514,62],{"emptyLinePlaceholder":61},[44,516,517,519,521,523,525,527],{"class":46,"data-line":211,"line":211},[44,518,68],{"class":50},[44,520,200],{"class":54},[44,522,75],{"class":74},[44,524,78],{"class":74},[44,526,82],{"class":81},[44,528,85],{"class":74},[44,530,531,533,535,537,539,541,543],{"class":46,"data-line":223,"line":223},[44,532,92],{"class":91},[44,534,255],{"class":50},[44,536,258],{"class":50},[44,538,75],{"class":98},[44,540,78],{"class":98},[44,542,82],{"class":81},[44,544,85],{"class":98},[44,546,548,550,552,554,556,558,560,562,564,566,568,570,572],{"class":46,"data-line":547,"line":547},18,[44,549,92],{"class":91},[44,551,92],{"class":91},[44,553,274],{"class":50},[44,555,277],{"class":81},[44,557,280],{"class":50},[44,559,283],{"class":54},[44,561,75],{"class":316},[44,563,78],{"class":316},[44,565,290],{"class":81},[44,567,293],{"class":50},[44,569,297],{"class":296},[44,571,82],{"class":81},[44,573,85],{"class":316},[44,575,577,579,581,583,585,587,589,592,594],{"class":46,"data-line":576,"line":576},19,[44,578,92],{"class":91},[44,580,92],{"class":91},[44,582,92],{"class":91},[44,584,310],{"class":81},[44,586,313],{"class":54},[44,588,75],{"class":74},[44,590,591],{"class":179},"\"recover捕获到异常值为:\"",[44,593,322],{"class":81},[44,595,101],{"class":74},[44,597,599,601,603,605],{"class":46,"data-line":598,"line":598},20,[44,600,92],{"class":91},[44,602,92],{"class":91},[44,604,39],{"class":81},[44,606,107],{"class":316},[44,608,610,612,614,616,618],{"class":46,"data-line":609,"line":609},21,[44,611,92],{"class":91},[44,613,39],{"class":81},[44,615,337],{"class":98},[44,617,75],{"class":98},[44,619,101],{"class":98},[44,621,623,625,628,631,633,636],{"class":46,"data-line":622,"line":622},22,[44,624,92],{"class":91},[44,626,627],{"class":81},"wg.",[44,629,630],{"class":54},"Add",[44,632,75],{"class":98},[44,634,635],{"class":296},"1",[44,637,101],{"class":98},[44,639,641,643,645,647,649],{"class":46,"data-line":640,"line":640},23,[44,642,92],{"class":91},[44,644,38],{"class":50},[44,646,434],{"class":54},[44,648,75],{"class":98},[44,650,101],{"class":98},[44,652,654,656,658,661,663],{"class":46,"data-line":653,"line":653},24,[44,655,92],{"class":91},[44,657,627],{"class":81},[44,659,660],{"class":54},"Wait",[44,662,75],{"class":98},[44,664,101],{"class":98},[44,666,668,670,672,674,676,679],{"class":46,"data-line":667,"line":667},25,[44,669,92],{"class":91},[44,671,310],{"class":81},[44,673,313],{"class":54},[44,675,75],{"class":98},[44,677,678],{"class":179},"\"无法捕获\"",[44,680,101],{"class":98},[44,682,684],{"class":46,"data-line":683,"line":683},26,[44,685,107],{"class":74},[23,687,228],{},[34,689,691],{"className":355,"code":690,"language":357,"meta":39,"style":39},"root@pzj:\u002Fcode\u002Fdemo\u002Fpanic# go run main.go\n准备panic\npanic: 子goroutine报错了\n\ngoroutine 6 [running]:\nmain.doSomething()\n        \u002Fcode\u002Fdemo\u002Fpanic\u002Fmain.go:11 +0x90\ncreated by main.main in goroutine 1\n        \u002Fcode\u002Fdemo\u002Fpanic\u002Fmain.go:18 +0x31\nexit status 2\n",[41,692,693,707,712,720,724,746,755,767,787,799],{"__ignoreMap":39},[44,694,695,698,701,704],{"class":46,"data-line":47,"line":47},[44,696,697],{"class":54},"root@pzj:\u002Fcode\u002Fdemo\u002Fpanic#",[44,699,700],{"class":179}," go",[44,702,703],{"class":179}," run",[44,705,706],{"class":179}," main.go\n",[44,708,709],{"class":46,"data-line":58,"line":58},[44,710,711],{"class":54},"准备panic\n",[44,713,714,717],{"class":46,"data-line":65,"line":65},[44,715,716],{"class":54},"panic:",[44,718,719],{"class":179}," 子goroutine报错了\n",[44,721,722],{"class":46,"data-line":88,"line":88},[44,723,62],{"emptyLinePlaceholder":61},[44,725,726,729,732,734,737,740,743],{"class":46,"data-line":104,"line":104},[44,727,728],{"class":54},"goroutine",[44,730,731],{"class":296}," 6",[44,733,82],{"class":81},[44,735,736],{"class":74},"[",[44,738,739],{"class":81},"running",[44,741,742],{"class":74},"]",[44,744,745],{"class":81},":\n",[44,747,748,751,753],{"class":46,"data-line":110,"line":110},[44,749,750],{"class":54},"main.doSomething",[44,752,75],{"class":74},[44,754,101],{"class":74},[44,756,757,759,761,764],{"class":46,"data-line":115,"line":115},[44,758,271],{"class":91},[44,760,271],{"class":91},[44,762,763],{"class":54},"\u002Fcode\u002Fdemo\u002Fpanic\u002Fmain.go:11",[44,765,766],{"class":179}," +0x90\n",[44,768,769,772,775,778,781,784],{"class":46,"data-line":131,"line":131},[44,770,771],{"class":54},"created",[44,773,774],{"class":179}," by",[44,776,777],{"class":179}," main.main",[44,779,780],{"class":179}," in",[44,782,783],{"class":179}," goroutine",[44,785,786],{"class":296}," 1\n",[44,788,789,791,793,796],{"class":46,"data-line":143,"line":143},[44,790,271],{"class":91},[44,792,271],{"class":91},[44,794,795],{"class":54},"\u002Fcode\u002Fdemo\u002Fpanic\u002Fmain.go:18",[44,797,798],{"class":179}," +0x31\n",[44,800,801,804,807],{"class":46,"data-line":148,"line":148},[44,802,803],{"class":296},"exit",[44,805,806],{"class":179}," status",[44,808,809],{"class":296}," 2\n",[23,811,812],{},"可以看到子 goroutine 直接 panic 了，而主 goroutine 捕获是没有用的，查看输出",[23,814,815,816,819],{},"发现",[26,817,818],{},"无法捕获","没有输出，说明在子 goroutine panic 后直接就退出了，根本就不会回到 main，所以 recover 只能恢复当前 goroutine 的 panic，无法恢复其他 goroutine 的",[821,822,823],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sSDpw, html code.shiki .sSDpw{--shiki-default:#005cc5;--shiki-dark:#79b8ff}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJX2D, html code.shiki .sJX2D{--shiki-default:#e36209;--shiki-dark:#ffab70}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sqkie, html code.shiki .sqkie{--shiki-default:#5a32a3;--shiki-dark:#b392f0}",{"title":39,"searchDepth":88,"depth":88,"links":825},[],[827],"Go语言","2025-08-07","Go 中的 `panic` 会导致当前 goroutine 崩溃，若未被 `recover` 捕获，则程序终止。`recover` 需配合 `defer` 使用，只能捕获**当前 goroutine** 内的 panic。若 panic 发生在子 goroutine 中，主 goroutine 的 `recover` 无法捕获，程序仍会崩溃，因此每个 goroutine 内需单独设置 `defer+recover` 才能防止异常扩散。",false,"md",null,{"slots":834},{},"\u002F2025\u002F08\u002Fgo-panic",{"text":837,"minutes":838,"time":839,"words":840},"3 min read",2.105,126300,421,{"title":5,"description":829},{"loc":835},"posts\u002F2025\u002F08\u002Fgo-panic",[174],"tech","G5pVQ5va4DqJZxXsmjRp9ujOTdno6wr1jL0FmCesdmY",[848,852],{"title":849,"path":850,"stem":851,"date":828,"type":845,"children":-1},"使用 Go Channel 实现简易 EventBus","\u002F2025\u002F08\u002Fgo-channel5","posts\u002F2025\u002F08\u002Fgo-channel5",{"title":853,"path":854,"stem":855,"date":856,"type":845,"children":-1},"go jwt和redis实现用户登录注册以及查询","\u002F2025\u002F08\u002Fgo-jwt-redis-demo","posts\u002F2025\u002F08\u002Fgo-jwt-redis-demo","2025-08-08",1786555056471]