한 눈에 끝내는 고랭 기초
    • 01
      시작하기에 앞서
    • 강의대상
      Go란?
      실습 환경 구축 - 구름IDE
      Hello goorm! 출력해보기
    • 02
      변수와 상수
    • 콘솔 출력 함수의 기본
      변수의 선언과 초기화
      상수의 선언과 초기화
      간단한 덧셈
      잘못된 신상정보
    • 03
      연산자
    • 연산자 종류
      연산자 우선순위
      콘솔 입력 함수의 기본
      간단한 덧셈과 곱셈
      몫과 나머지
    • 04
      자료형
    • 자료형의 종류와 특징
      문자열의 표현
      자료형의 변환
      강제 형 변환
    • 05
      콘솔 출력과 입력 함수
    • 콘솔 출력 함수(Print)
      콘솔 입력 함수(Scan)
      정돈된 표
      신상정보 입력과 출력
    • 06
      반복문 - for
    • 오로지 for
      구구단
      빛나는 이등변삼각형
    • 07
      조건문 - if/else
    • 조건에 따른 실행과 흐름 분기
      7과 9의 배수
      두 수의 차
    • 08
      분기문 - switch
    • swich문에 의한 선택적 실행
      안좋은 계산기
    • 09
      제어문
    • break, continue, goto문
      구구단2
      두 수를 더하면 99
    • 10
      컬렉션
    • 배열(Array)
      슬라이스(Slice)
      맵(Map)
      역행렬
      가장 긴 이름
      중간고사 평균 점수
    • 11
      함수
    • Go언어에서의 함수
      전역변수와 지역변수
      매개변수
      반환값(리턴값)
      익명 함수
      오름차순 정렬
      아이패드를 사주는 조건
      역학적 에너지
    • 12
      클로저
    • 외부 변수 접근 : 클로저
      동전 정리
    • 13
      구조체와 메소드
    • 구조체
      메소드
      성적 저장 프로그램
      역학적 에너지2
    • 14
      인터페이스(interface)
    • 메소드의 집합 인터페이스
      직육면체와 원기둥
    • 15
      defer와 panic()
    • 지연 처리 defer
      종료하는 panic(), 복구하는 recover()
      엘리베이터
      중간고사 평균 점수2
    • 16
      에러 처리
    • 에러 처리의 기본
      에러 출력 및 처리
      중간고사 평균 점수3
    • 17
      고루틴(Goroutine)
    • 비동기 프로세스의 기본
      고루틴의 활용
      고루틴 실습
    • 18
      채널(Channel)
    • 고루틴의 데이터 통로 : 채널
      비동기 채널과 버퍼
      동기 채널
      채널 닫기
      송신 전용, 수신 전용 채널
      채널 select문
      고루틴 실습2
      메시지 전송
      동기 채널 실습
      비동기 채널 실습
    • 19
      패키지(package)
    • 패키지의 개념
    • 20
      실전 프로젝트 - 마일리지 상점
    • 프로젝트를 시작하기 앞서
      실습모드에서 실습
      마일리지 상점의 주요 기능
      필수 구조체와 매인 메뉴
      잔여 수량, 잔여 포인트 구현
    • 21
      실전 프로젝트 - 주문하기, 장바구니 담기
    • 구매 구현(1)
      구매 구현(2)
      장바구니에 담기
      장바구니 확인(1)
      장바구니 확인(2)
    • 22
      실전 프로젝트 - 고루틴으로 배송하기
    • 배송 상태 확인(1)
      배송 상태 확인(2)
      배송 상태 확인(3)
      최종 코드
    지연 처리 defer
    15 defer와 panic()
    지연 처리 defer

    지금까지 강의는 Go언어의 다양한 용법중에서도 '문법'에 해당되는 내용을 학습했습니다. 용법이 문법을 포함하는 뜻이지만, 용법과 문법은 사용에 있어서 차이가 있습니다. 용법은 어떠한 것을 사용하는 방법이자 전체적인 흐름을 고려했을 때 마땅히 해야하는 것이고, 프로그래밍 언어에서의 문법은 어떠한 기능과 구문을 사용하기 위해 반드시 따라야하는 규칙을 말합니다. 영어로 예를 들어보겠습니다. 

    "저는 축구를 할 것입니다." 라는 말을 영어로 바꿨을 때 , "I will playing soccer."라고 썼다면 문법이 틀린 것입니다. 반면에, 용법이라는 것은 영어를 사용하면서 전체적인 흐름이나 표현을 알맞게 사용하는 것을 말합니다. 누군가가 당신에게 감사를 표시했을 때 "My pleasure."이라고 말하는 것이 자연스러운 것처럼 말입니다. 따라서 이번 강의부터 프로그램을 제작하면서 마땅히 필요하고, 사용하는 것이 자연스러운 용법에 관해 학습해보겠습니다.


    마지막에 꼭 실행하는 defer


    defer는 함수 앞에 쓰이는 키워드로써 특정 문장 혹은 함수를 감싸고 있는 함수 내에서 제일 나중에, 끝나기 직전에 실행하게 하는 용법입니다. Java를 사용해본 개발자는 try ~finally 구문과 유사한 기능을 한다고 하면 감이 올 것입니다. try ~finally 구문과 비슷하게 동작하지만 좀 더 간결하게 쓸 수 있습니다. try ~fianlly 구문은 사실 catch 키워드와 함께 구문을 실행하고 오류를 처리하고 마지막에 할당된 공간을 반납하는 흐름으로 실행됩니다. 아래는 Java에서 쓰이는 try ~catch ~finally 구문입니다.

    java

    다른 언어에서는 위에서 보여준 형태로 쓰입니다. 보기에도 형식이 확실히 정해져있다는 느낌이 들 것입니다. 하지만 defer는 블록이 필요한 것도 아니고 특정 위치나 형식이 필요한 것도 아닙니다. 단지 함수 앞에 defer를 명시함으로써 사용하는 것입니다. 

    "마지막에 꼭 실행한다."라는 느낌이 무엇인지 감이 잘 안 올 수 있습니다. 쉽게 말해서, 프로그램의 흐름에 분기가 많아 '예외 처리'가 많아 복잡할 때 유용하게 사용합니다. defer를 사용하면 흐름 중간에 에러(예외)가 발생해도 마지막에 꼭 실행하고 프로그램을 종료하지 않는 것입니다.


    우선,  아래 간단한 예시 코드로 defer의 사용 형태를 확인해보겠습니다. 바로 실행해보세요.

    go
    실행 결과를 확인해보세요!

    순서상으로는 "world Hello"가 출력될 것 같지만 지연 실행 defer 키워드를 fmt.Println("world") 앞에 입력했기 때문에 fmt.Println("Hello") 구문을 먼저 실행하고 main() 함수가 종료되기 직전 마지막에 실행됩니다. 이를 활용해 defer는 프로그램을 실행하면서 예상하지 못한 에러(다음 강의에서 학습할 'panic')가 발생 했을 때 프로그램을 종료하지 않고 defer 구문을 실행할 때 유용하게 쓰입니다.


    아래 예시를 통해 defer의 핵심 역할을 알아보겠습니다. 바로 실행해보세요.

    go
    실행 결과를 확인해보세요!

    위 코드에서는 어떤 수를 0으로 나누면서 에러가 발생합니다. 이는 패닉 에러에 대표적인 예입니다. 코드의 문법상으로는 전혀 문제 되는 것이 없습니다. 그런데 프로그램이 시작되고 연산을 하면 에러가 발생하게 됩니다. 이때 에러가 발생하고 바로 종료되는 것이 아니라 미리 선언해두었던 defer 구문이 마지막으로 실행되고 종료되는 것입니다. 그리고 만약에 defer 구문을 에러가 발생하는 코드 뒤에 선언하면 호출되지 않고 프로그램이 종료됩니다. 따라서 에러가 발생하는 코드 전에 선언해야합니다. 이러한 기능은 파일을 열고 닫을 때 활용됩니다.


    여기서 궁금한 것이 생길 수 있습니다. "그럼 defer를 사용한 함수들이 여러개면 어떤 함수가 먼저 호출되는걸까?" 이 궁금증을 해소하기 위해서 아래 코드를 바로 실행해보세요.

    go
    실행 결과를 확인해보세요!

    위는 단순히 fmt.Println() 함수를 hello()world() 함수로 선언해서 함수 호출시 사용법을 표현한 것입니다. 실행해보면 defer를 사용한 함수가 역순으로 실행되는 것을 알 수 있습니다. 이것은 자료구조의 스택(LIFO)과 동일한 것인데, 제일 나중에 지연 호출한 함수가 제일 먼저 실행되는 것입니다.(지연 호출된 함수 중에서)

    위에 defer 키워드는 파일을 열고 닫을 때 많이 활용된다고 언급했습니다. 왜냐하면 파일을 열거나 읽어들이면서 에러가 발생하면 파일을 닫을 수 없게 되기 때문입니다. 물론 다른 부분에도 많이 사용되지만 파일 입/출력에는 꼭 필요한 '용법'이라는 것을 알아두기를 바랍니다. 그리고 아직 파일 입/출력을 다루지는 않았지만 간단한 흐름과 활용법에 대해서만 보여주겠습니다.


    아래 간단한 파일을 열고 읽어들이는 과정에서 defer 용법을 사용한 예시 코드가 있습니다. 흐름만 파악하기 바랍니다. 파일이 존재하지 않기 때문에 실행하면 에러가 발생합니다.

    go
    실행 결과를 확인해보세요!

    파일 입/출력이 생소하기 때문에 천천히 다루겠습니다. 우선 파일과 관련된 함수를 사용하려면 "os" 패키지를 import 해야 합니다.  그리고 위 코드에서 아직 배우지 않은 에러 처리가 있습니다. 에러 처리와 관련된 함수는 배우지 않았지만 간단하게 알아보겠습니다. 

    우선, os.Open("test.txt")를 입력해서 같은 디렉터리에 있는 test.txt 파일을 엽니다. 여기서 Open() 함수는 '파일'과 '에러 값'으로 반환값이 두 개입니다.  파일을 file 변수에 초기화하고 에러 값을 err 변수에 초기화합니다. err 값이 존재하면(nil이 아니라는 말과 동일) 아래에 if문을 실행돼서 err 값을 출력하고 함수 호출을 종료(return)합니다. 이때 지연 처리의 용법이 필요한 것입니다. Helloworld() 함수가 return 되기 전에 defer file.Close() 함수를 실행합니다. 즉, 파일을 닫습니다. 그래서 프로그램이 오류가 발생하더라도 defer 키워드를 사용해 파일을 닫고 다음 코드를 실행할 수 있는 것입니다.

    그리고 바로 buf 변수에 byte형 슬라이스를 생성하고 아래 if문에서 에러 처리와 file.Read(buf)로 불러온 파일을 읽고 초기화합니다. 여기서도 마찬가지로 err 값이 있다면 err 값을 출력하고 return 전에 defer file.Close() 함수를 실행합니다. 그리고 파일의 내용을 출력하고 main() 함수에 fmt.Println("Done")을 실행합니다. 지연 처리를 통해 꼭 파일을 닫기 때문에 이 구문은 항상 실행할 수 있습니다.

    default

    설치 없이 바로 실행 가능한 클라우드 IDE인 구름IDE를 이용해 디렉터리에 test.txt파일을 생성하고 실행해본 결과입니다. test.txt에 아무것도 입력하지 않고 실행했을 때 "EOF"라고 에러가 출력되고 프로그램이 종료되는 것이 아니라 "Done"이 출력됩니다. 

    default

    이번엔 test.txt에 "Hello world!"를 입력하고 실행한 결과입니다. 에러 처리가 되지 않았기 때문에 실행된 다음 "Done"이 출력되는 것을 확인할 수 있습니다.

    질문하기