Local Helper Closure
지역 헬퍼 함수
- 함수 내부에서만 사용하는 익명 함수(Anonymous Function) 를 변수에 할당하여 사용하는 기법
- 부모 함수의 변수를 캡처(Capture) 하여 인자 전달을 최소화하고, 반복되는 로직을 제거
e.g.
1func BuildControllers(ctx context.Context, controllerCtx ControllerContext, controllerDescriptors map[string]*ControllerDescriptor,
2 unsecuredMux *mux.PathRecorderMux, healthzHandler HealthCheckAdder) ([]Controller, error) {
3 ...
4 buildController := func(controllerDesc *ControllerDescriptor) error {
5 controllerName := controllerDesc.Name()
6 ctrl, err := controllerDesc.BuildController(ctx, controllerCtx)
7 ...
8 controllers = append(controllers, ctrl)
9 checks = append(checks, check)
10 return nil
11 }
12 ...
13 for _, controllerDesc := range controllerDescriptors {
14 ...
15 if err := buildController(controllerDesc); err != nil {
16 return nil, err
17 }
18 }
19 ...
20}
장점
- 중복 코드 제거 가능
- 함수 인자 단순화
- 함수 인자 대신 외부 변수를 캡쳐해서 사용(클로저)
- 전역 변수 없이 상태 공유
- 스코프 내의 지역 변수들을 공유
- 캡슐화/격리
- 스코프 내에서만 사용 가능
주의
- 단위 테스트 작성 불가
- 함수형 프로그래밍 관점에서는 순수하지 않은(impure) 함수
- 너무 많은 외부 변수 캡쳐는 지양
- 가독성을 위해 짧게 유지하는 것이 좋음
- Loop Variable Capture 이슈
- Go 1.21 이하: 루프 변수(
v)는 반복문이 돌 때마다 새로 생성되는 게 아니라, 하나의 메모리 주소를 계속 덮어씀- Go 1.22 이상: 루프의 각 반복(Iteration)마다 변수를 새로 생성(Shadowing)