defer는 function이 return하기 직전에 실행한다. C#에서 유사한 문법으로는 finally가 있으며, 주로 메모리 활당해제와 같은 clean-up을 위해 사용된다. 예를 들어 파일 읽기와 같은 작업을 수행할 때 defer를 사용하여 file을 open 후 다음 라인에서 defer close를 작성하여 추후에 close하는 것을 망각하는 것을 방지 가능하다.
파일을 오픈 후 defer를 이용하여 function(TestFileOpen) return 직전 f.close()를 호출
func TestFileOpen(t *testing.T) {
fileName := "./test.txt"
f, _ := os.Open(fileName)
defer f.Close()
contents, err := io.ReadAll(f)
if err != nil {
t.Error(err)
}
t.Log(string(contents))
}
1.선입 후출(FILO) 방식으로 동작

2.종속해 있는 function의 retrun 직전에 실행한다.

3.defer fn()에서 전달되는 Parameter는 defer의 선언된 라인의 parameter의 상태가 전달된다. 파라미터로 전달되지 않은 값은 fn의 return직전의 값을 참조한다.
func TestParameter(t *testing.T) {
num := 0
fmt.Printf("currnet num : %v \n", num)
defer func(val int) {
fmt.Printf("first func i : %v \n", num)
fmt.Printf("first func value : %v \n", val)
}(num)
for i := 0; i < 10; i++ {
num++
}
defer func(val int) {
fmt.Printf("second func i : %v \n", num)
fmt.Printf("second func value : %v \n", val)
}(num)
}

4.return은 defer보다 먼저 실행된다.
func TestDeferAndReturn(t *testing.T) {
func() (int, error) {
defer fmt.Println("defer")
return fmt.Println("function")
}()
}
!

5.Panic 발행 시, 현재 stack에 쌓여있는 것들만 LIFO 순서로 실행된다.
func TestDeferPanic(t *testing.T) {
defer printOut("a")
defer printOut("b")
defer printOut("c")
panic("panic here")
defer printOut("d")
printOut("end of function")
}

defer mu.unlock과 같이 defer를 사용하면 코드가 더욱 깔끔해지고, 실수를 줄일 수 있다. 하지만 특성을 잘 모른다면 실수하기 쉬움, 특히 변수를 전달할 때는 명확하게 사용하여야 한다.
갈수록 포스팅 퀄이 좋아지네요 잘보고 갑니다