go

Go 클로저(closure)

까오기 2024. 7. 11. 12:22

Go 언어에서 클로저 (closure)는 함수와 그 함수가 선언될 당시의 외부 변수를 함께 포함한 것입니다. 클로저는 함수 리터럴로 만들어지며, 해당 함수 리터럴은 자신이 선언된 범위(scope) 내의 변수를 계속 유지하면서 사용할 수 있습니다. 이는 함수가 종료된 이후에도 그 변수가 사라지지 않고, 계속해서 접근 가능하게 만듭니다.

클로저의 구조

Go에서 클로저는 다음과 같은 구조를 가집니다:

 
func outerFunction() func() {
    outerVariable := 10
    innerFunction := func() {
        fmt.Println("Outer variable inside closure:", outerVariable)
    }
    return innerFunction
}

func main() {
    closure := outerFunction()
    closure() // "Outer variable inside closure: 10" 출력
}

위 예제에서 outerFunction은 함수를 반환합니다. 반환된 함수인 innerFunction은 외부 변수 outerVariable을 참조하고 있습니다. 이렇게 외부 변수를 참조하는 함수 리터럴이 클로저가 됩니다.

클로저의 특성

  1. 외부 변수의 캡처: 클로저는 자신이 선언된 시점에서 외부 변수의 값을 캡처(capture)합니다. 따라서 클로저를 생성한 함수가 종료된 이후에도 외부 변수에 접근할 수 있습니다.
  2. 변수의 지역성 유지: 클로저는 외부 변수를 유지하므로, 이 변수는 클로저가 존재하는 동안 계속 유지됩니다. 이는 변수의 지역성(locality)을 유지하는 데 도움을 줍니다.
  3. 사용 예시: 클로저는 고루틴(Goroutine)과 함께 사용되어 비동기 처리를 구현하는 데 유용합니다. 또한 함수를 반환하는 패턴에서 상태(state)를 유지하면서 다양한 동작을 정의할 수 있습니다.

클로저 사용 예제

 
package main

import "fmt"

func counter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

func main() {
    c := counter()
    fmt.Println(c()) // 1 출력
    fmt.Println(c()) // 2 출력
    fmt.Println(c()) // 3 출력
}

 

위 예제에서 counter 함수는 클로저를 반환합니다. 반환된 클로저는 count 변수를 캡처하고 있으며, 호출될 때마다 count를 증가시킨 후 그 값을 반환합니다. 이로 인해 main 함수에서 c 클로저를 호출할 때마다 카운트가 증가하게 됩니다.

주의할 점

  • 클로저가 캡처한 변수는 해당 변수가 메모리에서 해제되기 전까지 유지됩니다. 따라서 클로저가 사용하는 변수가 너무 많거나 너무 큰 경우 메모리 누수(memory leak)가 발생할 수 있습니다.
  • 클로저는 고루틴과 함께 사용될 때 특히 유용합니다. 각 고루틴은 자신이 캡처한 변수를 공유하며, 이를 통해 동기화 없이도 상태를 관리할 수 있습니다.

클로저는 Go 언어에서 함수형 프로그래밍과 상태 관리를 유연하게 처리하는 중요한 도구입니다. 함수를 반환하거나 변수에 할당할 수 있는 Go의 특성과 함께 클로저를 잘 이해하고 활용한다면 코드를 더욱 모듈화하고 가독성 있게 작성할 수 있습니다.

 

출처 : chatGPT