수색…


소개

defer 문은 함수 호출을 목록으로 푸시합니다. 저장된 호출 목록은 주변 함수가 리턴 한 후에 실행됩니다. Defer는 일반적으로 다양한 정리 작업을 수행하는 기능을 단순화하는 데 사용됩니다.

통사론

  • defer someFunc (args)
  • defer func () {// 코드는 여기에있다.} ()

비고

Defer는 현재 실행중인 함수 아래의 호출 스택에 새 스택 프레임 ( defer 키워드 다음에 호출 된 함수)을 주입하여 작동합니다. 이것은 스택이 unwound 될 때까지 연기가 보장됨을 의미합니다 (프로그램이 충돌하거나 SIGKILL 얻었을 때 연기는 실행되지 않습니다).

연기 기본 사항

Go의 지연 명령문 은 나중에 실행되도록 표시된 함수 호출입니다. Defer 문은 키워드 defer 시작하는 일반 함수 호출입니다.

defer someFunction()

defer 문을 포함하는 함수가 반환되면 지연 함수가 실행됩니다. 지연 함수에 대한 실제 호출은 다음 함수를 포함 할 때 발생합니다.

  • return 문을 실행합니다.
  • 끝에서 떨어지다
  • 공황

예:

func main() {
    fmt.Println("First main statement")
    defer logExit("main") // position of defer statement here does not matter
    fmt.Println("Last main statement")
}

func logExit(name string) {
    fmt.Printf("Function %s returned\n", name)
}

산출:

First main statement
Last main statement
Function main returned

함수에 여러 개의 지연된 명령문이 있으면 스택을 형성합니다. 마지막 defer 은 enclosing 함수가 반환 된 후에 실행되는 첫 번째 defer 이며, 그 다음에 이전 defer 에 대한 후속 호출이 순서대로 수행됩니다 (예를 들어 패닉이 발생하여 반환됩니다).

func main() {
    defer logNum(1)
    fmt.Println("First main statement")
    defer logNum(2)
    defer logNum(3)
    panic("panic occurred")
    fmt.Println("Last main statement") // not printed
    defer logNum(3) // not deferred since execution flow never reaches this line
}

func logNum(i int) {
    fmt.Printf("Num %d\n", i)
}

산출:

First main statement
Num 3
Num 2
Num 1
panic: panic occurred

goroutine 1 [running]:
....

지연 함수는 defer 실행될 때 평가 된 인수 defer .

func main() {
    i := 1
    defer logNum(i) // deferred function call: logNum(1)
    fmt.Println("First main statement")
    i++
    defer logNum(i) // deferred function call: logNum(2)
    defer logNum(i*i) // deferred function call: logNum(4)
    return // explicit return
}

func logNum(i int) {
    fmt.Printf("Num %d\n", i)
}

산출:

First main statement
Num 4
Num 2
Num 1

함수의 이름이 반환 값 인 경우 해당 함수 내의 지연 익명 함수는 함수가 반환 된 후에도 반환 된 값에 액세스하고 업데이트 할 수 있습니다.

func main() {
    fmt.Println(plusOne(1)) // 2
    return
}

func plusOne(i int) (result int) { // overkill! only for demonstration
    defer func() {result += 1}() // anonymous function must be called by adding ()

    // i is returned as result, which is updated by deferred function above
    // after execution of below return
    return i
}

마지막으로, defer 문은 일반적으로 함께 사용되는 연산으로 일반적으로 사용됩니다. 예 :

  • 파일 열기 및 닫기
  • 연결 및 연결 해제
  • 뮤텍스 잠금 및 잠금 해제
  • 대기 그룹을 완료로 표시합니다 ( defer wg.Done() ).

이 사용은 실행 흐름과 관계없이 시스템 리소스의 적절한 릴리스를 보장합니다.

resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close() // Body will always get closed

지연된 함수 호출

지연 함수 호출은 Java와 같은 언어에서 finally 블록과 비슷한 목적을 수행합니다. 즉, 오류가 발생했는지 또는 여러 반환이있는 경우에 return 문이 실행되었는지 여부에 관계없이 외부 함수가 반환 될 때 일부 함수가 실행되도록합니다. 네트워크 연결이나 파일 포인터처럼 닫아야하는 리소스를 정리할 때 유용합니다. defer 키워드는 새로운 goroutine을 시작하는 go 키워드와 비슷하게 지연 함수 호출을 나타냅니다. go 호출과 마찬가지로 함수 인수는 즉시 평가되지만 go 호출과 달리 지연된 함수는 동시에 실행되지 않습니다.

func MyFunc() {
    conn := GetConnection()    // Some kind of connection that must be closed.
    defer conn.Close()        // Will be executed when MyFunc returns, regardless of how.
    // Do some things...
    if someCondition {
        return                // conn.Close() will be called
    }
    // Do more things
}// Implicit return - conn.Close() will still be called

사용 주 conn.Close() 대신 conn.Close - 당신은 당신이 인수를 포함하여 전체 함수 호출을 연기하고, 함수를 전달 아닙니다. 다중 함수 호출은 동일한 외부 함수에서 지연 될 수 있으며 각 함수는 역순으로 한 번 실행됩니다. 또한 마감을 연기 할 수 있습니다 - 단지 괄호를 잊지 마세요!

defer func(){
    // Do some cleanup
}()


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow