[Go] Error, Panic 핸들링 (stacktrace)

natae·2022년 9월 18일
1

Golang

목록 보기
9/11

개요

  • 런타임중 panic이 발생했을 경우, stacktrace가 출력되고 프로그램이 종료됨
    • panic은 다른 언어의 Exception과 유사
  • recover 및 추가 작업을 통해 프로그램 종료 없이 stacktrace 출력 구현
    • recover는 다른 언어의 try...catch와 유사
  • 또한 error가 발생한 경우에도 stacktrace를 출력 가능하도록 구현

코드1 (error 생성할때 stacktrace 추가)

errors.go

package errors

import (
	"errors"
	"fmt"
	"runtime"
)

func New(message string) error {
	stackTraceBuf := make([]byte, 1<<10) // 1kb
	runtime.Stack(stackTraceBuf, true)

	return errors.New(fmt.Sprintf("%s\n, %s", message, stackTraceBuf))
}

repository.go

package repository

import (
	"apiserver/server/model"
	"apiserver/server/errors"
)

type AccountRepository struct {
	//TODO:  dbAccessor...
}

func (r *AccountRepository) Select(nickname string) (*model.Account, error) {	
	return nil, errors.New("Not implement")
}

출력1

[Error] Not implement
, goroutine 20 [running]:
apiserver/server/errors.New({0x7b1871, 0xd})
        D:/Dev/project/golang_APIServer/app/server/errors/errors.go:11 +0x4d
apiserver/server/repository.(*AccountRepository).Select(...)
        D:/Dev/project/golang_APIServer/app/server/repository/account.go:14
apiserver/server/service.(*AccountService).GetAccount(...)
        D:/Dev/project/golang_APIServer/app/server/service/account.go:13
apiserver/server/controller.(*AccountController).login(0xc0000ce0e0, 0xc0000fa9a0)
        D:/Dev/project/golang_APIServer/app/server/controller/account.go:31 +0x73
github.com/gofiber/fiber/v2.(*App).next(0xc0000d0f00, 0xc00025c000)
        C:/Users/natae/go/pkg/mod/github.com/gofiber/fiber/v2@v2.37.1/router.go:132 +0x1be
github.com/gofiber/fiber/v2.(*Ctx).Next(0xc00025e020)
        C:/Users/natae/go/pkg/mod/github.com/gofiber/fiber/v2@v2.37.1/ctx.go:892 +0x53
apiserver/server.ResponsePrintMiddleware(0xc00025c000)
        D:/Dev/project/golang_APIServer/app/server/middleware.go:35 +0x25
github.com/gofiber/fiber/v2.(*Ctx).Next(0x7b0b6b)
        C:/User...

코드2 (panic 발생시 프로그램 종료없이 stacktrace 출력)

recover.go

func PrintPanicStack() {
	defer func() {
		if r := recover(); r != nil {
			stackTraceBuf := make([]byte, 1<<10) // 1kb
			runtime.Stack(stackTraceBuf, true)

			fmt.PrintF("PrintPanicStack: %v\n %s", r, stackTraceBuf)
		}
	}()
}

repository.go

package repository

import (
	"apiserver/server/model"
)

type AccountRepository struct {
	//TODO:  dbAccessor...
}

func (r *AccountRepository) Select(nickname string) (*model.Account, error) {
	panic("Sorry")	
}

출력2

[Error] PrintPanicStack: Sorry
 goroutine 7 [running]:
apiserver/server.RecoverAndStackTraceMiddleware.func1()
        D:/Dev/project/golang_APIServer/app/server/middleware.go:15 +0x7e
panic({0xdb77e0, 0xe87ac0})
        C:/Program Files/Go/src/runtime/panic.go:1038 +0x215
apiserver/server/repository.(*AccountRepository).Select(...)
        D:/Dev/project/golang_APIServer/app/server/repository/account.go:12
apiserver/server/service.(*AccountService).GetAccount(...)
        D:/Dev/project/golang_APIServer/app/server/service/account.go:13
apiserver/server/controller.(*AccountController).login(0xc0000060f0, 0xc00013a840)
        D:/Dev/project/golang_APIServer/app/server/controller/account.go:31 +0xfc
github.com/gofiber/fiber/v2.(*App).next(0xc000118f00, 0xc00029c000)
        C:/Users/natae/go/pkg/mod/github.com/gofiber/fiber/v2@v2.37.1/router.go:132 +0x1be
github.com/gofiber/fiber/v2.(*Ctx).Next(0xc00029e020)
        C:/Users/natae/go/pkg/mod/github.com/gofiber/fiber/v2@v2.37.1/ctx.go:892 +0x53
apiserver/server.ResponsePrintMiddleware(0xc00029c000)
        D:/Dev/project/golang_APIServer/app...

결론

  • 자세한 코드는 github 참고
  • error에 stacktrace 추가하는 부분은 빈번하게 error가 발생할 경우, 부하를 발생시킬 수 있어서, 필요한 부분만 사용하는 게 좋을 것 같음
profile
서버 프로그래머

0개의 댓글