Goでクロージャを使用する理由

Go言語

クロージャという関数内で定義された関数があるのをご存知でしょうか?
今回クロージャをGoで実際に使うと何が便利かということを今回紹介します。

クロージャとは

クロージャーとは、関数内で定義された関数のことです。例として、関数A内で定義された関数Bは、関数A内で定義された変数を使用したり、変更することができる。この関数Bのことをクロージャと呼んでいる。
このクロージャの利点は二つある。
1つ目は、関数のスコープを制限することができる。関数Aからしか呼び出されないが、関数Aから何度も呼び出される場合、関数Bを隠して関数内の関数として使用ができる。そうすることで宣言の数が減るので、名前の衝突の危険が少なくなる。
2つ目は、関数の中で定義された変数をその環境ごと包み込んで持ち出して、関数の外でも使用することができる。

使用例

sortで使用する例.

sort.Search()の第二引数にクロージャを渡してあげて、昇順にソートすることが可能になる。

ソース

package main

import (
	"fmt"
	"sort"
)

func main() {
	var list []int = []int{3, 5, 1, 4, 2}
	fmt.Println("変更前:", list)

	// 第二引数にクロージャを渡している
	// main内で定義された配列のlistにアクセスできる。
	sort.Slice(list, func(i, j int) bool {
		return list[i] < list[j]
	})
	fmt.Println("変更後:", list)
}

実行結果

listがソートされて、昇順に出力されること。

変更前: [3 5 1 4 2]
変更後: [1 2 3 4 5]

関数の中で定義された変数をその環境ごと包み込んで持ち出して、関数の外でも使用する例.

関数の中で定義された変数をその環境ごと包み込んで持ち出して、関数の外でも使用することができる例として、クロージャが呼ばれる毎に、渡した値ずつ値を増やしていくincrementerを実装する。

ソース

package main

import "fmt"

// 返されるクロージャが呼ばれる毎にbaseの値分増える。
func incrementer(base int) func() int {
	i := 0
	return func() int {
		i = i + base
		return i
	}
}

func main() {
	oneIncrementer := incrementer(2)
	for i := 0; i < 5; i++ {
		// 呼ばれる毎にカウントが増えていることを確認
		fmt.Println(oneIncrementer())
	}
}

実行結果

2づつ数値が上がっている。

2
4
6
8
10

まとめ

今回はGoのクロージャについてまとめてみました。
この記事以外にもGoの学習ロードマップや、Goの並行処理を使うために必要な知識であるchannelやselectの仕組みについて書いた記事がありますので、そちらも読んでもらえたらと思います。

【おすすめ記事のリンク】

コメント

タイトルとURLをコピーしました