정상우
hELLO.
정상우
전체 방문자
384,472
오늘
91
어제
1,174
  • hELLO. (121)
    • 컴퓨터과학 (4)
      • 알고리즘 & 자료구조 (4)
    • 언어 & 프레임워크 (63)
      • Go (23)
      • PHP & Laravel (40)
    • 웹 (7)
    • 블록체인 (12)
      • 메인넷 (9)
      • 암호화폐 플랫폼 (3)
    • 포트폴리오 (10)
    • 칼럼 (20)
      • 에세이 (4)
      • 개발자스럽게 살기 (14)
      • 회고 (2)
    • 티스토리 (5)

블로그 메뉴

  • ⚡ 개발자 이력서
  • 🌟 깃허브
  • 💻 강의
  • ✨ 예제코드
  • ⭐ 브런치
  • 태그 클라우드
  • 방명록

공지사항

  • 2차 도메인을 설정했습니다 ✨

인기 글

  • JWT(JSON Web Token)의 개념부⋯
    2021.07.29
    JWT(JSON Web Token)의 개념부⋯
  • 'REST' 를 보다 'RESTful' 하게⋯
    2021.08.14
    'REST' 를 보다 'RESTful' 하게⋯
  • [Laravel] 라라벨 프레임워크⋯
    2021.06.10
    [Laravel] 라라벨 프레임워크⋯
  • 깃허브를 포트폴리오로 쓰려면⋯
    2021.12.25
    깃허브를 포트폴리오로 쓰려면⋯
  • 암호화폐 트레이딩 봇을 만들었⋯
    2021.05.12
    암호화폐 트레이딩 봇을 만들었⋯

태그

  • php
  • go
  • 블록체인
  • 포트폴리오
  • 개발
  • 라라벨
  • 프로그래머스
  • Algorithm
  • 코딩테스트
  • 개발 리뷰

최근 댓글

  • 고맙습니다 ~^^
    정상우
  • 오늘 블로그 만들었는데 검색하⋯
    엥뿌삐
  • 좋은 스킨 정말 감사드립니다.⋯
    이태홍
  • 고맙습니다 ㅎㅎ
    정상우
  • 제가 원하던 최고의 스킨입니다⋯
    _HEON

최근 글

  • 빠르게 성장하는 개발자의 세⋯
    2022.06.08
    빠르게 성장하는 개발자의 세⋯
  • 개발자와 엔지니어, 그 사이에서
    2022.05.10
    개발자와 엔지니어, 그 사이에서
  • 아임포트(Iamport)로 결제기능⋯
    2022.04.03
    아임포트(Iamport)로 결제기능⋯
  • 아임포트(Iamport)로 결제기능⋯
    2022.04.01
    아임포트(Iamport)로 결제기능⋯
  • [Laravel] 카페24 호스팅에 라⋯
    2022.03.29
    [Laravel] 카페24 호스팅에 라⋯

티스토리

hELLO · Designed By 정상우.
정상우

hELLO.

언어 & 프레임워크/Go

Go: recover() 를 사용하여 복구하기 [Effective Go]

2021. 1. 3. 21:15

recover() 함수를 사용하여 panic() 에서 어플리케이션을 복구할 때 사용할 수는 몇 가지 기법을 Effective Go 에서 보여주고 있다. 이 포스트에서 이야기해 볼 것은 두 가지, 다수의 고루틴을 돌릴 때 다른 고루틴에게 피해를 주지 않고 실패한 고루틴만 로깅하기와 패닉, 한 번 더 패닉이다. 패닉과 에러에 대한 기초적인 내용은 다른 포스트에 적은 바 있다.

 

Go: 에러와 패닉 (panic, recover)

 

Go: 에러와 패닉 (panic, recover)

예외가 없다고? 그렇다. Go 언어에는 예외(Exception)가 없다. 에러로 모든 것을 처리한다. error 빌트인 타입은 존재하긴 하지만, 그렇다고 타언어처럼 모든 에러에 대해 타입이 매핑되어 있는 것은

pronist.tistory.com

실패한 고루틴만 로깅하기

각 고루틴이 어떤 조건에 도달하면 패닉을 일으키되, 로깅을 하고 고루틴을 마친다. 정상적으로 종료되는 것이므로 패닉이 발생한 상태를 회복한 것이라 볼 수 있다. 이는 아래와 같이 해볼 수 있다. 해당 고루틴은 랜덤으로 생성한 정수값이 2 로 나누어지면 패닉을 일으키는 단순한 예제다. 

var wg sync.WaitGroup

func doSomething(id int) {
	rand.Seed(int64(id))

	defer func() {
		if err := recover(); err != nil {
			fmt.Fprintf(os.Stderr, "goroutine #%d, got %v, want %v %% 2 != 0\n", id, err, err)
		}
	}()
	defer wg.Done()

	randomInt := rand.Intn(100) + 1
	if randomInt % 2 == 0 {
		panic(randomInt)
	}

	fmt.Println(randomInt)
}

func do() {
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go doSomething(i)
	}
	wg.Wait()
}

do() 함수에서 10개의 고루틴을 만들고, 각 고루틴마다 recover() 를 포함한 지연된 호출을 가지고 있기 때문에 만약 고루틴을 실행하던 도중, 패닉이 발생한다고 해도 다른 고루틴에게는 영향을 주지 않는다. 다음의 예는 해당 프로그램을 실행했을 때의 결과 중 하나다.

9
89
49
87
87
27
75
goroutine #4, got 30, want 30 % 2 != 0
goroutine #1, got 78, want 78 % 2 != 0
goroutine #9, got 2, want 2 % 2 != 0

패닉, 한 번 더 패닉

패닉을 복구시키되 만약 사전에 정의된 패닉이 아니라 예상하지 못한 패닉이라면 패닉을 한 번 더 발생시켜 에러를 처리할 수 있다. 예를 들면 다음과 같이 Error 타입이 있다고 가정했을 때, 해당 타입이 패닉으로 전달되지 않은 경우에는 예상하지 못한 패닉으로 간주하고 패닉을 발생시킬 수 있다.

type Error string

func (e Error) Error() string {
	return string(e)
}

func do() {
	defer func() {
		if err := recover(); err != nil {
			err, ok := err.(Error)
			if !ok {
				panic(err)
			}
			fmt.Fprintf(os.Stderr, err.Error())
		}
	}()
	doSomething()
}

여기서 doSomething() 함수에서 어떤 패닉이 발생하냐에 따라 분기가 달리게 되는데, 다음과 같은 형태로 발생하면 패닉이 아니라 로깅이 정상적으로 이루어진다.

func doSomething() {
	panic(Error("Hello, Go!"))
}

이런 식으로 호출되었을 때, 패닉이 발생하지 않는 이유는, do() 함수의 지연된 호출에서 타입 단언이 성공했기 때문이다. 만약 알려지지 않은 타입이어서 타입 단언이 실패한다면, 다시 한 번 패닉이 발생하게 된다.

    '언어 & 프레임워크/Go' 카테고리의 다른 글
    • Go 언어를 공부하기 위한 자료 및 문서 정리
    • Go: 변수 스코프와 블록
    • Go: 웹 서버 구축하기 (net/http, html/template)
    • Go: Switch 를 사용하여 타입 체크하기 (Reflection) [Effective Go]
    effective go, go, Panic, recover
    정상우
    정상우
    과거의 배움으로 현재를 바꾸고 미래를 만듭니다. #25+2살 #INFJ #개발자 #브런치작가
    댓글쓰기
    다음 글
    Go: 변수 스코프와 블록
    이전 글
    2020년 회고―, 시작
    • 이전
    • 1
    • ···
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • ···
    • 121
    • 다음

    티스토리툴바