0Pricing
Go Academy · レッスン

動的な関数呼び出し

reflectを使って関数を呼び出し、値を設定します。

「動的な関数呼び出し」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

reflect.Value.Call

Value.Call(args) は、指定した引数([]reflect.Value)を使って Value が表す関数を呼び出し、結果を []reflect.Value として返します。

fn := reflect.ValueOf(add)
results := fn.Call([]reflect.Value{
    reflect.ValueOf(2),
    reflect.ValueOf(3),
})
fmt.Println(results[0].Int()) // 5

引数の型チェック

呼び出す前に、引数の型が関数シグネチャと一致していることを確認します。型が一致しないとパニックになります。

t := reflect.TypeOf(fn)
if t.NumIn() != len(args) { panic("wrong arg count") }
for i, arg := range args {
    if !reflect.TypeOf(arg).AssignableTo(t.In(i)) { panic("type mismatch") }
}

可変長関数

Value.Call(スライスを展開して渡す)または Value.CallSlice(可変長引数をスライス値として渡す)で可変長関数を呼び出します:

sum := reflect.ValueOf(func(ns ...int) int {
    total := 0
    for _, n := range ns { total += n }
    return total
})
args := reflect.ValueOf([]int{1,2,3})
results := sum.CallSlice([]reflect.Value{args})

reflect.MakeFunc

reflect.MakeFunc は、指定した型とラッパー本体を持つ新しい関数を実行時に作成します。インターフェース用のアダプター関数を生成するために使用します。

t := reflect.TypeOf(func(int) string { return "" })
fn := reflect.MakeFunc(t, func(args []reflect.Value) []reflect.Value {
    return []reflect.Value{reflect.ValueOf(strconv.Itoa(args[0].Interface().(int)))}
})

名前によるメソッド呼び出し

名前でメソッドを取得して呼び出します:

v := reflect.ValueOf(myObj)
m := v.MethodByName("Process")
if m.IsValid() {
    m.Call(nil)
}

メソッドの存在確認

呼び出す前に必ず m.IsValid() を確認してください。MethodByName はメソッドが見つからない場合にゼロ値の Value を返し、ゼロ値の Value を呼び出すとパニックになります。

動的ディスパッチのユースケース

動的な関数呼び出しは、プラグインシステム(文字列名で関数を呼び出す)、テストフレームワーク(TestXxx 関数を呼び出す)、RPC ディスパッチャー(メソッド名をハンドラーに対応付ける)、デコレーターで使用されます。

パフォーマンス

reflect.Call は直接呼び出す場合より約 10~50 倍遅くなります。頻繁に呼び出す関数の reflect.Value をキャッシュし、ホットループ内での使用は避けてください。

型安全なラッパー

動的な呼び出しを型付きヘルパーでラップします。このヘルパーは起動時に一度だけリフレクション処理を行い、キャッシュした Value を繰り返し呼び出します:

type Processor func(context.Context, []byte) ([]byte, error)
// Build at startup, reuse at request time

エラー戻り値の処理

関数の最後の戻り値がエラーの場合は、それを取り出して確認します:

results := fn.Call(args)
if !results[len(results)-1].IsNil() {
    return results[len(results)-1].Interface().(error)
}

リフレクションの代替手段

関数の集合がコンパイル時に決まっている場合は、リフレクションではなく関数値のマップ(map[string]func(...))を使用します。こちらのほうが安全で高速です。

handlers := map[string]func(ctx context.Context, req []byte) []byte{
    "greet": greetHandler,
}

確認問題

reflect.Value.Call は何を返しますか?

まとめ: 動的な関数呼び出し

重要なポイント:

  • Value.Call([]reflect.Value) は関数を呼び出し、[]reflect.Value を返す
  • MethodByName の結果を呼び出す前に m.IsValid() を確認する
  • MakeFunc は指定した型の新しい関数を実行時に作成する
  • 関数の集合が既知の場合は、リフレクションより map[string]func を優先する

よくある質問

「動的な関数呼び出し」レッスンは無料ですか?

はい。「動的な関数呼び出し」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「動的な関数呼び出し」で何を学びますか?

reflectを使って関数を呼び出し、値を設定します。 ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「動的な関数呼び出し」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. reflect.Typeとreflect.Value
  2. 構造体フィールドとタグの調査
  3. 動的な関数呼び出し
  4. 実践リフレクション:シリアライザー
← Go Academyに戻る