Go言語の高階関数の基本!関数を引数に渡す方法
生徒
「先生、Go言語で関数をほかの関数に渡すことができるって聞きました。どういう意味ですか?」
先生
「それは『高階関数(こうかいかんすう)』と呼ばれるもので、関数を引数として渡せる仕組みのことです。これを使うとコードをもっと便利で柔軟に書けますよ。」
生徒
「関数を引数に渡すって、ちょっとイメージがわかないです。具体的に教えてもらえますか?」
先生
「もちろんです。わかりやすく説明していきますね!」
1. 高階関数とは?
「高階関数(こうかいかんすう)」とは、関数を値として扱える考え方のことです。具体的には、関数をほかの関数の引数として渡したり、逆に処理の結果として戻り値として返したりできます。Go言語では関数も数値や文字列のように一種のデータとして扱えるため、処理の差し替えや共通化がとても簡単になります。たとえば、「料理のレシピ」に対して「ソースをかける手順」を差し替えるように、やり方(関数)を外から渡して実行するイメージです。
初心者の方は「関数=箱」と考えると理解しやすいでしょう。箱の中には「やりたい処理」が入っており、その箱ごと別の関数に手渡すことで、受け取った側は中身の処理を好きなタイミングで実行できます。これがコールバックやイベント処理、配列の加工などでよく使われる基本パターンです。
下の短い例は、Go言語で「関数を引数に渡す」雰囲気をつかむためのミニサンプルです(仕組みの詳細は次の章で順に説明します)。
package main
import "fmt"
// 関数を引数に受け取って実行する高階関数
func apply(action func(string) string, name string) {
fmt.Println(action(name))
}
func main() {
// 関数をそのまま渡す(無名関数でもOK)
hello := func(s string) string { return "こんにちは、" + s }
apply(hello, "太郎")
}
ここではactionという「やり方」を外から受け取り、applyが中で呼び出しています。つまり、動作の具体的な中身を後から差し替えられるのが高階関数の強みです。Go言語の高階関数は、関数を引数に渡す、無名関数をその場で作って渡す、コールバックとして実行する、といった柔軟な書き方につながります。
2. Go言語で関数を引数に渡す方法
Go言語では、関数を普通の値(例えば数字や文字列と同じように)として扱えるため、引数に関数を渡せます。
具体的には、関数の引数に「関数の型」を指定して、その関数を呼び出せるようにします。
func process(f func(int) int, value int) int {
return f(value)
}
ここで、process関数は、func(int) intという型の関数fと、整数valueを引数に受け取っています。
そして、渡された関数fにvalueを渡して結果を返しています。
3. 関数を引数に渡す実例
では、実際に関数を引数に渡してみましょう。
func square(x int) int {
return x * x
}
func main() {
result := process(square, 5)
fmt.Println(result) // 25
}
squareという関数を作り、それをprocess関数に渡しています。
process関数は、渡されたsquare関数を実行して結果を返しています。
4. 無名関数(名前のない関数)を使って渡す方法
関数を一時的に作って渡す場合は、「無名関数」と呼ばれる名前のない関数を使います。
例えば、次のように書きます。
func main() {
result := process(func(x int) int {
return x + 10
}, 5)
fmt.Println(result) // 15
}
このように、関数を直接引数の場所に書いて渡せます。簡単な処理をその場で書くのに便利です。
5. 高階関数を使うメリット
- 処理の共通部分をまとめてコードを簡単にできる
- 繰り返し使う動作を外から差し替えられる
- コードの再利用性が高まる
例えば、数字を加工する処理が複数あるとき、共通の処理関数に加工方法の関数だけ渡すと楽に書けます。
6. 高階関数を使うと何がうれしい?
今回はGo言語の高階関数について学びました。
高階関数は「関数を引数に渡せる関数」のことで、関数を自由に組み合わせて使うことができます。
無名関数を使うことで、その場で処理を作って渡せるのも便利です。
この考え方を理解すると、プログラムがより柔軟で読みやすくなります。
まとめ
今回はGo言語でとても重要な考え方である高階関数について、関数を引数に渡す仕組み、無名関数で一時的な処理を定義する方法、そしてコードの再利用性を高める書き方まで、ひと通り整理しました。高階関数という言葉は難しそうに聞こえますが、実際には「関数という道具を箱のように扱い、それを別の関数に渡して処理を変化させる」だけです。数字を二倍にする、引き算をする、文字列を加工する、どんな処理でも関数にしてしまえば、共通の流れの中で差し替えることができ、複雑なロジックを簡潔に整理できます。 Go言語は構文がシンプルで覚えやすい一方、書き方に慣れていない初心者のうちは、同じような処理を何度も書いてしまいがちです。そのような場面こそ、高階関数が活躍します。例えば「数字を加工して結果を返す」という枠だけ決めておき、加工方法は外から渡すようにすれば、重複が消えて保守しやすくなります。特に、無名関数をすぐに書いてそのまま渡せる点はとても便利で、一時的なルールや試し書きにも向いています。 実際の開発では、配列やスライスに対するフィルタリング、マッピング、集計のような処理でも高階関数が役に立ちます。もし同じようなループを何度も書いていると感じた場合、共通の流れを一か所にまとめて、変えたい部分だけ関数にして渡すように考えると、コードが読みやすくなり、後から見たときの理解もしやすくなります。複雑なプログラムほど、こうした再利用できる形にしておくことが、結果として時間の節約にもつながります。
サンプルプログラムでもう一度整理
同じ仕組みでも、使い方次第で表現が増えることを確認してみましょう。次の例では、同じ数字に対して複数の処理を差し替えています。
package main
import "fmt"
type Op func(int) int
func apply(x int, f Op) int {
return f(x)
}
func main() {
r1 := apply(3, func(n int) int { return n * 3 })
r2 := apply(3, func(n int) int { return n - 1 })
r3 := apply(3, func(n int) int { return n + 10 })
fmt.Println(r1, r2, r3)
}
applyという共通の枠を作り、その枠の中身だけ無名関数で変えています。同じ数字でも、三倍、マイナス一、十を足す、など自由に差し替えができる点が高階関数の魅力です。処理が多くなっても、差し替えたい部分だけを書くので、読んだ人にとっても理解がしやすく、動きの違いもはっきりします。
実際の開発で役立つ場面
開発では、ログの書き換え、エラーチェック、入力データの整形など、ほんの一部分だけ違う処理を差し込みたい場面が出てきます。処理の流れを毎回書くのではなく、外から渡して差し替えられるようにすると、テストもしやすく、将来の修正にも強くなります。特に関数の引数で振る舞いを切り替える書き方は、Go言語のコードを多く読むと頻繁に見かけるため、知っておくと理解のスピードも上がります。
初心者のうちは「関数を変数のように扱える」という発想そのものが新しく感じるかもしれません。数値や文字列と同じように、関数にも型があり、引数に渡せる、戻り値にできるという仕組みを理解すると、プログラムの見える世界が広がります。無理に難しい書き方をする必要はありませんが、同じ処理が増えてきたら、関数として切り出して渡す習慣をつけると、自然とコードが整っていきます。
生徒
「今日の高階関数、最初は難しそうでしたが、実際に書いてみると意外とシンプルでした。関数を引数に渡すだけなんですね。」
先生
「そうなんです。言葉が難しいだけで、仕組みはとても素直ですよ。処理の流れと、差し替えたい部分を分けて考えるだけで、コードの見通しがずいぶん良くなります。」
生徒
「無名関数をそのまま渡せるのも便利でした。ちょっとした計算なら別で定義しなくても使えますね。」
先生
「その通り。一時的なルールを書きたいときに役立ちます。慣れてくると、スライスの加工やデータの整形でも自然に使うようになりますよ。」
生徒
「次はスライスの処理にも応用してみます。関数を渡す考え方が理解できると、いろんな書き方ができる気がして楽しいです。」
先生
「その気持ちがあれば大丈夫です。難しそうに感じる場面でも、共通の部分と差し替える部分を整理すると、必ず書けるようになりますよ。」