panic, recover 및 defer
언제 panic을 사용하고 어떻게 우아하게 복구할지 학습합니다.
panic, recover 및 defer은(는) CoddyKit의 무료 Go Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Go Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
panic이란 무엇인가요
panic은 현재 고루틴의 정상 실행을 중단하고, 지연된 함수를 실행하면서 호출 스택을 되감습니다. 복구되지 않으면 프로그램이 종료됩니다:
package main
import "fmt"
func mustPositive(n int) int {
if n <= 0 {
panic(fmt.Sprintf("mustPositive: got %d", n))
}
return n
}
func main() {
fmt.Println(mustPositive(5)) // 5
// fmt.Println(mustPositive(-1)) // panics!
}panic을 사용하는 경우
다음과 같은 경우에만 panic을 사용하세요:
- 정말로 복구할 수 없는 프로그래머 오류(불변식 위반)
- 버그를 나타내는 불가능한 상태
- 시작 실패(설정 누락, 초기화 중 연결 실패)
예상 가능한 실패 상태에는 절대 panic을 사용하지 말고 error를 사용하세요.
defer 기초
defer는 둘러싼 함수가 반환될 때 함수를 호출하도록 예약합니다. 정상 반환, 오류 반환, 패닉 등 반환 방식과 관계없이 실행됩니다:
package main
import "fmt"
func main() {
defer fmt.Println("third")
defer fmt.Println("second") // LIFO order
defer fmt.Println("first")
fmt.Println("running...")
// Output:
// running...
// first
// second
// third
}정리를 위한 defer
defer의 가장 일반적인 용도는 리소스가 정리되도록 보장하는 것입니다:
package main
import ("fmt"; "os")
func readFile(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", fmt.Errorf("open: %w", err)
}
defer f.Close() // always runs, even if we return early
buf := make([]byte, 1024)
n, _ := f.Read(buf)
return string(buf[:n]), nil
}recover — 패닉 잡기
recover는 패닉을 중지하고 패닉 값을 반환합니다. defer 함수 내부에서 직접 호출해야 합니다:
package main
import "fmt"
func safeDiv(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("recovered from panic: %v", r)
}
}()
return a / b, nil // panics if b==0
}
func main() {
r, err := safeDiv(10, 0)
fmt.Println(r, err)
// 0 recovered from panic: runtime error: integer divide by zero
}recover는 지연된 함수 안에 있어야 합니다
recover는 지연된 함수 내부에서 직접 호출될 때만 작동합니다. 다른 곳에서 호출하면 nil을 반환합니다:
package main
import "fmt"
func wrong() {
// recover() here does nothing — not in defer
}
func correct() {
defer func() {
if r := recover(); r != nil {
fmt.Println("caught:", r)
}
}()
panic("oops")
}
func main() { correct() }라이브러리 코드의 패닉
라이브러리 코드는 호출자에게 패닉이 전달되도록 두어서는 거의 안 됩니다. 경계에서 패닉을 오류로 변환하세요:
package main
import ("fmt"; "runtime/debug")
func safeCall(fn func()) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v\n%s", r, debug.Stack())
}
}()
fn()
return nil
}
func main() {
err := safeCall(func() { panic("boom") })
fmt.Println(err != nil) // true
}defer의 LIFO 순서와 반복문 함정
지연된 호출은 후입선출(LIFO) 순서로 실행됩니다. 반복문 안에서 defer를 사용할 때는 주의하세요. 클로저나 도우미 함수를 사용하세요:
package main
import "fmt"
func processFiles(names []string) {
for _, name := range names {
name := name // capture loop variable
defer func() { fmt.Println("close:", name) }()
}
}
func main() {
processFiles([]string{"a.txt", "b.txt", "c.txt"})
// Output (LIFO): close: c.txt, close: b.txt, close: a.txt
}이름 있는 반환 값과 defer
지연된 함수는 이름 있는 반환 값을 읽고 수정할 수 있으므로 오류에 설명을 추가할 때 유용합니다:
package main
import "fmt"
func doWork() (err error) {
defer func() {
if err != nil {
err = fmt.Errorf("doWork: %w", err)
}
}()
return fmt.Errorf("something failed")
}
func main() {
err := doWork()
fmt.Println(err) // doWork: something failed
}panic과 error: 선택 가이드
panic과 error 중 선택하기:
- error 사용: 예상 가능한 실패(파일을 찾을 수 없음, 네트워크 시간 초과, 잘못된 입력)
- panic 사용: 프로그래밍 오류(nil 맵 접근, 범위를 벗어난 접근), 불가능한 상태, 초기화 실패
- API 경계를 넘어 panic을 사용하지 마세요. 호출자가 처리할 수 없습니다
- 서버에서는 종료를 방지하기 위해 고루틴의 최상위 수준에서 패닉을 복구하세요
빠른 확인
패닉을 잡으려면 recover()를 어디에서 호출해야 하나요?
복습: panic, recover, defer
요약:
panic: 스택을 되감고 지연된 함수를 실행하며, 복구되지 않으면 프로그램이 중단됩니다defer: 함수가 종료될 때(정상 종료, 오류 또는 패닉 발생 시) 실행되며 LIFO 순서를 따릅니다recover: 패닉을 중지하고 값을 반환하며, 반드시defer안에서 사용해야 합니다- 예상되는 실패가 아니라 프로그래머의 오류에 panic을 사용합니다
- API 경계에서 패닉을 오류로 변환합니다
자주 묻는 질문
“panic, recover 및 defer” 강의는 무료인가요?
네 — “panic, recover 및 defer” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Go Academy 강의 전체를 잠금 해제할 수 있습니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“panic, recover 및 defer”에서 뭘 배우나요?
언제 panic을 사용하고 어떻게 우아하게 복구할지 학습합니다. 브라우저에서 직접 실행하는 실습 코드로 Go Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Go Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Go Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“panic, recover 및 defer” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Go Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Go Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- error 인터페이스
- 사용자 지정 오류 만들기
- 오류 래핑과 언래핑
- panic, recover 및 defer