Skip to main content

defer

defer 키워드

Go의 defer

  • 목적: 함수가 종료될 때 실행할 작업을 예약하여 자원 해제 및 정리 작업을 보장.
  • 영어 의미: 미루다, 연기하다 (=put off)
  • 작동 방식:
    • 예약 시점: defer가 호출되면 해당 함수가 종료될 때 실행할 함수를 스택에 푸시(push).
    • 실행 시점: 예약된 함수는 예약된 순서의 역순(후입선출, LIFO)으로 실행됨.
  • 사용 예:
    • 파일 열기 및 닫기:
      file, err := os.Open("example.txt")
      if err != nil {
          // 오류 처리
      }
      defer file.Close() // 파일 닫기를 예약
      // 파일 작업 수행
      
    • 네트워크 연결:
      conn, err := net.Dial("tcp", "example.com:80")
      if err != nil {
          // 오류 처리
      }
      defer conn.Close() // 연결 닫기를 예약
      // 네트워크 작업 수행
      
    • 리소스 해제 보장: 함수 중간에 오류가 발생하더라도 함수가 종료될 때 예약된 작업이 실행됨.
  • 특징:
    • 여러 defer 사용 시, 예약된 순서의 역순으로 실행됨:
      defer fmt.Println("First")
      defer fmt.Println("Second")
      defer fmt.Println("Third")
      // 출력: Third, Second, First (함수 종료 시)
      

Java의 자원 관리 (try-with-resources)

  • 목적: 블록이 종료될 때 자동으로 자원을 닫아 자원 해제 및 정리 작업을 보장.
  • 구문: try-with-resources 구문을 사용하여, 자원을 자동으로 닫음.
  • 작동 방식:
    • try 블록이 끝나거나 예외가 발생하면, try 블록에서 선언된 자원이 자동으로 닫힘.
  • 사용 예:
    • 파일 열기 및 닫기:
      try (FileInputStream file = new FileInputStream("example.txt")) {
          // 파일 작업 수행
      } catch (IOException e) {
          // 오류 처리
      }
      // try 블록을 벗어나면 file이 자동으로 닫힘
      
    • 네트워크 연결:
      try (Socket socket = new Socket("example.com", 80)) {
          // 네트워크 작업 수행
      } catch (IOException e) {
          // 오류 처리
      }
      // try 블록을 벗어나면 socket이 자동으로 닫힘
      
  • 특징:
    • AutoCloseable 인터페이스를 구현한 자원만 사용 가능.
    • 예외가 발생하거나 정상적으로 블록을 벗어나더라도 자원이 자동으로 닫힘.

비교

  • 예약과 실행 시점:
    • Go의 defer: 함수 종료 시 예약된 작업을 역순으로 실행.
    • Java의 try-with-resources: try 블록이 종료되거나 예외가 발생할 때 자원을 자동으로 닫음.
  • 사용 편의성:
    • Go의 defer: 간단한 구문으로 다양한 작업을 예약 가능.
    • Java의 try-with-resources: AutoCloseable 인터페이스를 구현한 자원만 자동 닫기 가능.
  • 에러 처리:
    • Go: defer를 통해 예외가 발생하더라도 자원 해제를 보장.
    • Java: try-with-resources를 통해 예외가 발생하더라도 자원을 자동으로 닫음.

예제 비교

  • Go 예제:

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
        file, err := os.Open("example.txt")
        if err != nil {
            fmt.Println("Error:", err)
            return
        }
        defer file.Close() // 파일 닫기를 예약
    
        // 파일 작업 수행
    }
    
  • Java 예제:

    import java.io.FileInputStream;
    import java.io.IOException;
    
    public class Main {
        public static void main(String[] args) {
            try (FileInputStream file = new FileInputStream("example.txt")) {
                // 파일 작업 수행
            } catch (IOException e) {
                System.out.println("Error: " + e.getMessage());
            }
            // try 블록을 벗어나면 file이 자동으로 닫힘
        }
    }