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가 추가된 파일 이름이 만들어진다.