Go言語マスター 〜クロージャ・フィボナッチ関数の実装〜

公開日:2022-10-15
go

https://youtu.be/HRG-iamAMng

はじめに

Goの条件分岐・ループ処理・条件分岐について解説します。

Function closers

Goの関数はクロージャです。

例えば次のadder関数の例を見てみましょう。通常adder関数が呼ばれた後はメモリ解放されるため、変数sumは破棄されます。しかし、このadder関数は関数を返すため、返した関数はどこかで再び呼ばれることになります。この場合sumの値が保持されることになります。

今回の例ではsumが保持され続け、リターンした関数に値を渡すと、sumに数値が加算されていきます。

func adder() func(int) int {
  sum := 0
  return func(x int) int {
    sum += x
    return sum
  }
}

では動作を確認してみましょう。adder関数を2つ呼び出し、ループを行います。

func main() {
  pos, neg := adder(), adder()
  for i := 0; i < 10; i++ {
    fmt.Println(
      pos(i),
      neg(-2*i),
    )
  }
}
結果
0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90

posnegでそれぞれ別のメモリが確保されていることがあります。

Exercise: Fibonacci closure

フィボナッチ数列を出力するプログラムです。フィボナッチ数列とは0, 1, 1, 2, 3, 5, 8…という、前2つの数を足したものが次の要素になる数列です。

package main

import "fmt"

func fibonacci() func() int {
  f0 := 0
  f1 := 1
  return func() int {
    x := f0
    f0, f1 = f1, f0 + f1
    return x
  }
}

func main() {
  f := fibonacci()
  for i := 0; i < 10; i++ {
    fmt.Println(f())
  }
}
結果
0
1
1
2
3
5
8
13
21
34

初期値を変数f0f1に入れています。クロージャの機能により変数は破棄されないので、リターンする関数が呼ばれるたびに数列の値を1つずつ計算できます。
リターンした関数はmain内でfに代入され、for文により10回実行されます。

おわりに

今回は、Goでのクロージャについて解説しました。関数を返す際などに、意図しない挙動を起こさないよう理解しておきましょう。