티스토리 뷰

개발/GO

[Golang] defer

피클s 2022. 4. 4. 20:34

이 글은 Defer keyword in Go (Golang) - Welcome To Golang By Example 을 번역 및 재가공하여 작성하였습니다.

 

목차

     

    1. defer 키워드란?

    defer의 사전적 의미는 미루다, 연기하다 입니다.

    defer는 선언된 함수가 끝나기 직전에 실행됩니다.

     

    defer는 에러가 발생하여 비정상 종료가 될 때에도 실행됩니다.

    그래서 io를 close 하거나 에러를 캐치할 때에 사용됩니다.

    package main
    
    import (
        "fmt"
        "log"
        "os"
    )
    
    func main() {
        err := writeToTempFile("Some text")
        if err != nil {
            log.Fatalf(err.Error())
        }
        fmt.Printf("Write to file succesful")
    }
    
    func writeToTempFile(text string) error {
        file, err := os.Open("temp.txt")
        if err != nil {
            return err
        }
        defer file.Close()
    
        n, err := file.WriteString("Some text")
        if err != nil {
            return err
        }
        fmt.Printf("Number of bytes written: %d", n)
        return nil
    }

     

    2. 여러 형태의 실행방법

    2-1. 함수 실행

    package main
    import "fmt"
    func main() {
        defer test()
        fmt.Println("Executed in main")
    }
    func test() {
        fmt.Println("In Defer")
    }
    Executed in main
    In Defer

     

    2-2. 인라인 함수 실행

    인라인 함수는 끝에 ()를 붙여야 정상적으로 실행됩니다.

    package main
    
    import "fmt"
    
    func main() {
        defer func() { fmt.Println("In inline defer") }()
        fmt.Println("Executed")
    }
    Executed
    In inline defer

     

     

    3. defer가 작동하는 방식

    defer는 내부적으로 스택 데이터구조로 이루어져있습니다. 

    여러 defer가 선언되어 있다면 FILO(First In Last Out)순서로 실행됩니다.

    package main
    
    import "fmt"
    
    func main() {
    	defer fmt.Println("Defer in main")
    	fmt.Println("Stat main")
    	f1()
    	fmt.Println("Finish main")
    }
    
    func f1() {
    	defer fmt.Println("Defer in f1")
    	fmt.Println("Start f1")
    	f2()
    	fmt.Println("Finish f1")
    }
    
    func f2() {
    	defer fmt.Println("Defer in f2")
    	fmt.Println("Start f2")
    	fmt.Println("Finish f2")
    }
    Stat main
    Start f1
    Start f2
    Finish f2
    Defer in f2
    Finish f1
    Defer in f1
    Finish main
    Defer in main

     

    4. 파라메터가 실행되는 타이밍

    package main
    
    import "fmt"
    
    func main() {
    	sample := "abc"
    
    	defer fmt.Printf("In defer sample is: %s\n", sample)
    	sample = "xyz"
    }
    In defer sample is: abc

     

    defer가 출력한 sample은 abc였습니다.

    main함수가 종료될 때 sample은 xyz이지만 defer가 스택에 들어갈 때는 abc 이기때문에

    abc가 실행됩니다.

     

    5. defer와 named return value

    named return value 의 경우 defer에서 값이 수정될 수 있습니다.

    package main
    import "fmt"
    func main() {
        s := test()
        fmt.Println(s)
    }
    func test() (size int) {
        defer func() { size = 20 }()
        size = 30
        return
    }
    20

     

    6. defer와 panic

    panic이 발생하더라도 defer를 호출합니다.

    defer가 실행된 후에 에러 메세지가 출력이 됩니다.

    package main
    import "fmt"
    func main() {
        defer fmt.Println("Defer in main")
        panic("Panic with Defer")
        fmt.Println("After painc in f2")
    }
    Defer in main
    panic: Panic with Defer
    
    goroutine 1 [running]:
    main.main()
    	/tmp/sandbox2806734434/prog.go:7 +0x73
    
    Program exited.

     

     

    댓글
    공지사항
    최근에 올라온 글
    최근에 달린 댓글
    Total
    Today
    Yesterday
    링크
    «   2024/07   »
    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
    글 보관함