Golang_関数とクロージャ #467
Golangの関数はクロージャをサポートしています。これにより、コードの再利用性と柔軟性を高めることが可能です。それぞれに関して整理していきたいと思います。
Golangの関数
Golangにクラスの概念はありませんが、他のプログラミング言語と同様に関数は存在しています。
基本的な関数
基本的な構文は以下の通りです。
func functionName(parameter1 type1, parameter2 type2) returnType {
// 関数の処理
return result
}
例として単純な関数を定義してみます。
package main
import (
"fmt"
)
func add(a int, b int) int {
return a + b
}
func main() {
sum := add(3, 4)
fmt.Println("Sum:", sum) // 出力: Sum: 7
}
関数リテラル (無名関数)
Golangでは関数リテラル(無名関数)もサポートしており、関数を変数に代入したり、他の関数に引数として渡したりできます。
上記のadd関数を関数リテラルにしてみます。
package main
import (
"fmt"
)
func main() {
// 無名関数を変数に代入
add := func(a int, b int) int {
return a + b
}
sum := add(5, 7)
fmt.Println("Sum:", sum) // 出力: Sum: 12
}
Golangでは関数のこれらの機能を活かしてクロージャを実現します。
Golangのクロージャ
クロージャとは、関数とその関数が定義された環境(スコープ)を合わせたものです。
クロージャの基本
関数が定義された環境(スコープ)の変数を参照し、その変数の状態を保持します。これにより、関数が呼び出されるたびに、その外部変数にアクセスして変更を加えることができます。
実際のコードでクロージャの機能を見てみます。
package main
import "fmt"
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
func main() {
pos, neg := adder(), adder()
for i := 0; i < 10; i++ {
fmt.Println(
pos(i), // 0から始まり、次々と値を加算していく
neg(-2*i), // 0から始まり、次々と値を減算していく
)
}
}
adder()の冒頭でsumに0を代入していますが、posやnegにはreturn文の関数が入っている(そして外部変数にあたるsumにアクセスできる)ので、forでループしたとしてもsumが毎回0になってしまうわけではありません。
クロージャの使用場面
例えば以下のような場面で使用できます。
関数のカスタマイズ:
例)特定の設定を保持した関数を作成(以下は数字に常に特定の値を足す関数の例)
package main
import "fmt"
func makeAdder(x int) func(int) int {
return func(y int) int {
return x + y
}
}
func main() {
add5 := makeAdder(5)
fmt.Println(add5(3)) // 出力: 8
fmt.Println(add5(10)) // 出力: 15
}
関数の実行回数制限:
例)指定された回数だけ実行可能な関数
package main
import "fmt"
func makeLimitedFunc(limit int, fn func()) func() {
count := 0
return func() {
if count < limit {
count++
fn()
} else {
fmt.Println("Function limit reached")
}
}
}
func main() {
limitedFunc := makeLimitedFunc(3, func() { // 3回をlimitに設定
fmt.Println("Function called")
})
for i := 0; i < 5; i++ {
limitedFunc() // 4, 5回目はelseに入る
}
}
データのカプセル化:
クロージャを使用してデータをカプセル化し、外部からの直接的なアクセスを防ぐことができます。これはプライベート変数を保持する方法として役立ちます。
package main
import "fmt"
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
count := counter()
fmt.Println(count()) // 出力: 1
fmt.Println(count()) // 出力: 2
fmt.Println(count()) // 出力: 3
}
上記では「count := 0」がカプセル化された箇所で、ここには外部から直接アクセスできず、クロージャを通じてのみ操作されます。
ここまでお読みいただきありがとうございました!!
参考
この記事が気に入ったらサポートをしてみませんか?