더북(TheBook)

2.4.5 클로저

때로는 함수 이름을 지정하지 않고 익명 함수 형태로 사용할 때가 있다. Go에서 함수는 일급 객체(first-class object)이므로 변수의 값으로 사용할 수 있다. 다음과 같이 함수를 변수에 할당하여 변수처럼 사용할 수 있다.

fplus := func(x, y int) int {
    return x + y
}
fplus(3, 4)

익명 함수는 변수에 할당하지 않고 다음과 같이 바로 호출할 수도 있다.

func(x, y int) int {
    return x + y
}(3, 4)

코드를 보면 func 키워드 다음에 함수의 이름 없이 바로 매개변수 (x, y int)를 표시했다. 이어서 반환 타입을 선언하고 구현부를 작성했다. 마지막으로 (3, 4)로 함수를 호출했다.

이러한 익명 함수를 클로저(closure)라고 한다. 클로저는 선언될 때 현재 범위에 있는 변수의 값을 캡처하고, 호출될 때 캡처한 값을 사용한다. 클로저가 호출될 때 내부에서 사용하는 변수에 접근할 수 없더라도 선언 시점을 기준으로 해당 변수를 사용한다.

다음은 클로저를 사용한 팩토리 함수이다. 이 팩토리 함수는 파일의 확장자를 만들어주는 함수를 반환한다.

▼ 클로저를 사용한 팩토리 함수

package main
  
import (
    "fmt"
    "strings"
)
  
func makeSuffix(suffix string) func(string) string {
    return func(name string) string {
        if !strings.HasSuffix(name, suffix) {
            return name + suffix
        }
        return name
    }
}
  
func main() {
    addZip := makeSuffix(".zip")
    addTgz := makeSuffix(".tar.gz")
    fmt.Println(addTgz("go1.5.1.src"))
    fmt.Println(addZip("go1.5.1.windows-amd64"))
}

실행 결과

go1.5.1.src.tar.gz

go1.5.1.windows-amd64.zip

팩토리 함수 makeSuffix()suffix 변수를 캡처한 클로저를 반환한다. 이때의 suffix는 클로저가 생성될 때의 값이다. 파일 이름을 매개변수로 하여 클로저(addZip, addTgz)를 호출하면 suffix가 추가된 파일 이름이 만들어진다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.