[Golang] defer 익명함수 유무에 따른 차이점

hop6·2022년 2월 23일
0
type Number int

func (n Number) Print() {
	fmt.Println(n)
}

func Example() (n Number) {
	n = 10
    
    // 1
    defer n.Print()
    
    // 2
    defer func() {
    	n.Print()
    }()
    
    n += 10
    
    return
}

문제 : 위 Example() 이 1번 로직을 수행할 때와 2번 로직을 수행할 때 결과값이 다를까?

함수가 return 될 때, defer가 수행된다 해서... 같을 줄 알았는데, 결과값이 다르다.

20
10
---
즉,

1번 로직 결과 값 : 10
2번 로직 결과 값 : 20

??

함수를 실행하며 defer를 만나면 그 때 바로 defer stack에 넣어준다. ( return을 만나면 수행하기 시작하는 별도의 stack ? https://www.sohamkamani.com/golang/defer/ )
값이 다른 이유는,
defer n.Print() --> 스택에 바로 당시 시점의 n.Print()이 들어가고( n = 10 ), 차례가 오면 pop 되며, 10출력 ...
defer func() { n.Print() }() --> 스택에 함수가 들어가고< func() { n.Print() }() >, 차례가 오면 pop이 되고, 함수를 수행하며 그 시점의 n 값을 가져오기 때문에 20 출력 ( return을 만나기 직전의 n 값 )

( 위 말을 그림으로 표현 해봤습니다. )

위 전제가 맞을지 확인

func Example() (n Number) {
	n = 10
    
    // 1
    defer n.Print()
    
    n += 10
    
    // 2
    defer n.Print()
    
    // 3
    defer func() {
    	n.Print()
    }()
    
    n += 50
    
    // 4
    defer n.Print()
    
    
    // 5
    defer func() {
    	n.Print()
    }()
    
    n += 10
    
    return
}

결과값

80
70
80
20
10
---
즉,

1 : 10
2 : 20
3 : 80 (익명함수)
4 : 70
5 : 80 (익명함수)

예상대로 나온다.

결론 : defer 익명함수안에 코드를 넣으면 return 직전의 값들로 함수가 수행되고, 단순 코드만 넣으면 그 시점의 값들로 함수가 수행된다.

0개의 댓글