動的な関数呼び出し
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フィードバックを取得できます。ローカル設定は不要です。