パターン) ローカルヘルパークロージャ

ローカルヘルパークロージャ

ローカルヘルパー関数

  • 関数内部でのみ使用する 匿名関数 (Anonymous Function) を変数に割り当てて使用する手法
  • 親関数の変数を キャプチャ (Capture) することで、引数伝達を最小限に抑え、繰り返されるロジックを排除する

 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) 関数
  • 過度な外部変数キャプチャは避けるべき
  • 可読性のために短く保つのが良い
  • ループ変数キャプチャの問題
    • Go 1.21以下: ループ変数(v)は、ループが実行されるたびに新しく生成されるのではなく、一つのメモリアドレスを継続的に上書きする
    • Go 1.22以上: ループの各反復 (Iteration) ごとに変数を 新しく生成 (Shadowing)

Post
Category
Series