클로저: 함수 안에서 함수를 선언 및 정의할 수 있고, 바깥쪽 함수에 선언된 변수에도 접근할 수 있는 함수
바깥 함수가 변수와 자기 자신(함수)을 에워싸고(close over) 있다고 해서 클로저(closure)라고 한다 또한, 안쪽 함수 자체도 변수에 들어간다
// ↓ 함수 안에서
func main() {
// ↓ 익명 함수를 선언 및 정의
sum := func(a, b int) int {
return a + b
}
r := sum(1, 2) // 익명함수 사용
fmt.Println(r) // 3
}
func main() {
a, b := 3, 5
f := func(x int) int {
return a*x + b // 함수 바깥의 변수 a, b 사용
}
y := f(5)
fmt.Println(y) // 20
}
package main
import "fmt"
// ↓ 리턴 값이 익명 함수
func calc() func(x int) int {
a, b := 3, 5 // 지역 변수는 함수가 끝나면 소멸되지만
return func(x int) int {
return a*x + b // 클로저이므로 함수를 호출 할 때마다 변수 a와 b의 값을 사용할 수 있음
}
// ↑ 익명 함수를 리턴
}
func main() {
f := calc() // calc 함수를 실행하여 리턴값으로 나온 클로저를 변수에 저장
fmt.Println(f(1)) // 8
fmt.Println(f(2)) // 11
fmt.Println(f(3)) // 14
fmt.Println(f(4)) // 17
fmt.Println(f(5)) // 20
}
먼저 알아둘 부분은 함수에서 지역 변수는 함수 실행이 끝나면 소멸된다. 여기서 calc 함수는 y = ax + b를 구하는 클로저를 리턴하도록 구성되어 있다. 그리고 맨 처음에 f := calc()로 변수 f에 클로저를 저장하고 나면 calc 함수의 지역 변수인 a, b는 소멸됩니다. 하지만 그 아래 fmt.Println 부분을 보면 f 함수는 a, b의 값을 이용하여 정상적으로 값을 구하고 있다.
이처럼 클로저를 사용하면 지역 변수가 소멸되지 않고, 나중에 함수를 호출할 때마다 계속 가져다 쓸 수 있다. 즉, 클로저는 함수가 선언될 때의 환경을 계속 유지하고 있다. 다르게 이야기하면 프로그램의 흐름을 변수에 저장할 수 있습니다. 클로저는 함수형 언어의 큰 특징이며 Go 언어는 클로저를 통해 함수형 언어의 기능을 구현하고 있다.
func 함수명() func(매개변수명 자료형) 리턴값_자료형
따라서 정수형 매개변수, 정수형 리턴값 형태의 함수를 리턴한다면 func calc() func(x int) int가 됩니다.