Contents

[쉽고 빠르게 끝내는 GO언어 프로그래밍 핵심 기초 입문 과정] Section 10 : 에러 처리

인프런 쉽고 빠르게 끝내는 GO언어 프로그래밍 핵심 기초 입문 과정 강의 정리

10.1 에러처리

10.1.1 Go 에러

소프트웨어의 품질 향상에 가장 중요한 것 → 유형코드 및 에러 정보 등을 남기는 것

  • Go 에서는 기본적으로 error 라는 인터페이스 타입을 갖고 있다.
  • 개발자는 이 인터페이스를 구현하는 커스텀 에러 타입을 만들 수 있다.
1
2
3
type error interface {
    Error() string
}

10.1.2 Go 에러처리

  • Go 함수의 경우 기본적으로 리턴 타입을 두개 갖고 있다. (리턴값, 에러)
  • 주로 에러 타입을 리턴 하거나 Fatal(프로그램 종료) 메소드를 통해 에러를 출력한다.
  • os.Open() 함수는 첫번째는 File 포인터를 두번째는 error 인터페이스를 리턴한다.
1
2
3
func Open(name string) (*File, error) {
	return OpenFile(name, O_RDONLY, 0)
}

기본적인 메서드 에러 처리 예제

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package main

import (
	"fmt"
	"log"
	"os"
)

func main() {
	// 기본적인 메서드 에러 처리 예제
	f, err := os.Open("unnamedfile") // 예외 발생
	if err != nil {
		log.Fatal(err.Error()) // 프로그램 종료
		//log.Fatal(err)
	}

	fmt.Println("=======================")
	fmt.Println("Example 1 : ", f.Name())
}

errors 패키지의 New 메소드를 활용한 에러 생성

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package main

import (
	"errors"
	"fmt"
)

func main() {
	var err1 error = errors.New("Error occurred - 1")
	err2 := errors.New("error occurred - 2")

	fmt.Println("error1 : ", err1)
	fmt.Println("error1 : ", err1.Error())

	fmt.Println("error2 : ", err2)
	fmt.Println("error2 : ", err2.Error())

}

구조체를 사용하여 사용자 정의 예외처리 예제

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package main

import (
	"fmt"
	"log"
	"math"
	"time"
)

// 에러(예외) 처리 구조체
type PowError struct {
	time time.Time // 에러 발생 시간
	value float64  // 파라미터
	message string // 에러 메세지
	// value interface{}
}

func(e *PowError) Error() string {
	return fmt.Sprintf("[%v]Error - Input Value(value: %g) - %s", e.time, e.value, e.message)
}

func Power2(f, i float64) (float64, error) {
	if f == 0 {
		return 0, &PowError{time : time.Now(), value: f, message: "0은 사용할 수 없습니다."}
	}
	if math.IsNaN(f) {
		return 0, &PowError{time: time.Now(), value: f, message: "숫자가 아닙니다."}
	}
	if math.IsNaN(i) {
		return 0, &PowError{time: time.Now(), value: i, message: "숫자가 아닙니다."}
	}
	return math.Pow(f, i), nil
}

// Go 에러 처리 고급 - 3
func main() {

	// Example 1
	v, err := Power2(10, 3) // 정상
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Example 1 : ", v)

	// Example 2
	t, err := Power2(0, 3) // Error
	if err != nil {
		log.Fatal(err)
		fmt.Println(err.(*PowError).message)
	}
	fmt.Println("Example 1 : ", t)

}

10.2 recover, panic

10.2.1 panic 함수

  • Go 내장 함수인 panic() 함수는 현재 함수를 즉시 중지시키고 defer 함수를 호출하고 자기 자신을 호출한 곳으로 즉시 리턴한다.
  • 이러한 panic 모드 실행 방식은 다시 상위함수에도 똑같이 적용되고, 계속 콜스택을 타고 올라가며 적용된다. → 런타임 이외에 사용자가 코드 흐름에 따라 에러를 발생 시킬때 중요하다

panic 사용방법

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

import (
	"fmt"
)

func main() {
	fmt.Println("Start Main")
	panic("Error occurred : user Stopped!") // 방법1
	//log.Panic("Error occurred : user Stopped!") // 방법2
	fmt.Println("End Main")	// 실행 불가
}

10.2.2 recover 함수

  • Go 내장 함수인 recover() 함수는 패닉상태를 다시 정상상태로 되돌리는 함수이다.
  • panic에서 설정한 메세지를 받아 올 수 있다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

import (
	"fmt"
	"os"
)

func fileOpen(filename string) {
	// defer 함수 - panic이 호출 되면 실행
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("File Open Error! -> ", r)
		}
	}()

	f, err := os.Open(filename)
	if err != nil {
		panic(err)
	} else {
		fmt.Println("Filename : ", f.Name())
	}

	defer f.Close()
}

func main() {
	fileOpen("undefined.txt")
	fmt.Println("End Main.")
}