ホーム プログラミング言語 golang golang func Go 言語の匿名関数 – 関数名のない関数

Go 言語の匿名関数 – 関数名のない関数


 
 
Go 言語は匿名関数をサポートしています。つまり、使用する必要があるときに関数を定義します。匿名関数には関数名がなく、関数本体のみがあります。関数は、型として関数型の変数に割り当てることができます。匿名関数は、多くの場合、次のように渡されます。 C 言語のコールバック関数とは異なりますが、Go 言語ではコード内でいつでも匿名関数の定義をサポートしている点が異なります。

 

無名関数とは、関数名を定義する必要のない関数の実装方法を指し、関数名のない関数宣言と関数本体で構成されます。以下、無名関数の定義と使い方について詳しく説明します。

無名関数を定義する

無名関数の定義形式は以下のとおりです。

func(parameter list)(返回参数列表){
    コード
}

匿名関数定義は、名前のない通常の関数定義です。

1) 定義時に無名関数を呼び出す

匿名関数は宣言後に呼び出すことができます。次に例を示します。

func(data int) {
    fmt.Println("こんにちは", data)
}(100) 

3 行目の}の後の(100)に注目してください。これは、匿名関数を呼び出してパラメータを 100 として渡すことを意味します。

2) 無名関数を変数に代入します

たとえば、次のような匿名関数を割り当てることができます。

f := func(data int) {
    fmt.Println("hello", data)
}

f(100) 

匿名関数には幅広い用途があり、それ自体が一種の値であり、コールバック関数や操作のカプセル化を実装するためにさまざまなコンテナに便利に格納できます。

匿名関数はコールバック関数として使用されます

次のコードは、スライスに対するトラバーサル操作を実装します。トラバーサル内の各要素にアクセスする操作は、匿名関数を使用して実装されます。ユーザーは、さまざまな匿名関数本体を渡して、要素に対するさまざまなトラバーサル操作を実装できます。コードは次のとおりです:

package main

import (
    "fmt"
)

// スライスの各要素をループし、指定された関数で要素にアクセスする
func visit(list []int, f func(int)) {

    for _, v := range list {
        f(v)
    }
}

func main() {

    // 無名関数を使用してスライスの内容を印刷する
    visit([]int{1, 2, 3, 4}, func(v int) {
        fmt.Println(v)
    })
} 

コードの説明は次のとおりです。

  • 行 8 では、visit() 関数を使用して、トラバーサル プロセス全体をカプセル化しています。トラバーサル中にスライス値を取得したい場合は、コールバック パラメータを visit() に渡すだけです。
  • 18 行目では、整数スライス []int{1,2,3,4} を準備し、それをトラバーサル データとして visit() 関数に渡します。
  • 行 19 ~ 20 は、走査された各値を出力する機能を持つ無名関数を定義しています。

コールバック関数としての匿名関数の設計は Go 言語システム パッケージでも一般的であり、strings パッケージにも同様の設計があります。コードは次のとおりです。

 func TrimFunc(s string, f func(rune) bool) string {
    return TrimRightFunc(TrimLeftFunc(s, f), f)
}
匿名関数を使用した操作のカプセル化

次のコードは、匿名関数をマップのキー値として使用し、コマンド ライン パラメーターを通じて匿名関数を動的に呼び出します。

package main

import (
    "flag"
    "fmt"
)

var skillParam = flag.String("skill", "", "パフォームするスキル")

func main(){

    flag.Parse()

    var skill = map[string]func(){
        "fire": func() {
            fmt.Println("chicken fire")
        },
        "run": func() {
            fmt.Println("soldier run")
        },
        "fly": func() {
            fmt.Println("angle fly")
        },
    }

    if f, ok := skill[*skillParam]; ok {
        f()
    } else {
        fmt.Println("スキルが見つかりません")
    }

} 

コードの説明は次のとおりです。

  • 8行目はコマンドラインパラメータのスキルを定義しており、コマンドラインから –skill を入力して=の後の文字列をskillParamポインタ変数に渡します。
  • 行 12 はコマンド ライン パラメータを解析します。解析が完了すると、skillParam ポインタ変数はコマンド ラインに渡された値を指します。
  • 14 行目は、文字列から func() へのマップを定義し、マップを埋めます。
  • 15 行目から 23 行目はマップのキーと値のペアを初期化し、値は匿名関数です。
  • 26 行目では、skillParam は *string 型のポインター変数です。*skillParam を使用してコマンド ラインから渡された値を取得し、コマンド ライン パラメーターで指定された文字列に対応する関数をマップで検索します。
  • 29行目、マップ定義にこのパラメータがあればそれが呼び出され、それ以外の場合は「スキルが見つかりません」と出力されます。

コードを実行すると、結果は次のようになります。

PS D:\code> go run main.go --skill=fly
chicken fly
PS D:\code> go run main.go --skill=run
soldier run 
 

「 Go 言語の匿名関数 – 関数名のない関数」についてわかりやすく解説!絶対に観るべきベスト2動画

【初心者向け】JavaScriptの関数の仕組み・使い方を徹底解説! 関数宣言 / 無名関数 / アロー関数って何?【プログラミング入門】
#15 初見のGo言語で掲示板を作ってみる シャチョーのコードチャレンジ!