ホームページ > バックエンド開発 > Golang > Go 構造体の埋め込みインターフェイスにリフレクションを使用した関数実装があるかどうかを確実に検出するにはどうすればよいですか?

Go 構造体の埋め込みインターフェイスにリフレクションを使用した関数実装があるかどうかを確実に検出するにはどうすればよいですか?

Mary-Kate Olsen
リリース: 2024-12-22 19:35:11
オリジナル
424 人が閲覧しました

How Can I Reliably Detect If an Embedded Interface in a Go Struct Has a Function Implementation Using Reflection?

Struct の組み込みインターフェイスを使用した Go リフレクション

「実際の」関数の検出

Go のリフレクションパッケージは、実行時に型と値に関する情報へのアクセスを提供します。これは強力なツールですが、構造体内の組み込みインターフェイスを操作する場合は混乱を招く可能性もあります。

次の例を考えてみましょう。

type A interface {
    Foo() string
}

type B struct {
    A
    bar string
}
ログイン後にコピー

ご覧のとおり、Go は次のことを行いません。コンパイル時に埋め込みインターフェイスの実装を強制します。これは、実装を提供せずにインターフェイスを構造体に埋め込むことができることを意味します。

メソッドにアクセスするためのリフレクションの使用

リフレクション パッケージを使用して、オブジェクトからメソッドを取得できます。実装が提供されていない場合でも、構造体の埋め込みインターフェイス:

bType := reflect.TypeOf(B{})
bMeth, has := bType.MethodByName("Foo")
if has {
    fmt.Printf("HAS IT: %s\n", bMeth.Type.Kind())
    res := bMeth.Func.Call([]reflect.Value{reflect.ValueOf(B{})})
    val := res[0].Interface()
    fmt.Println(val)
} else {
    fmt.Println("DOESNT HAS IT")
}
ログイン後にコピー

ただし、埋め込みインターフェイスに実装がない場合、このコードはパニックになる可能性があります。

実装の不在​​の検出

埋め込みインターフェイスに実装がないかどうかを検出するには、関数へのポインタをチェックできます。匿名インターフェイス値の関数テーブル内:

b := B{}
bType := reflect.TypeOf(b)
bMeth, has := bType.MethodByName("Foo")
if has {
    bMethPtr := bMeth.Func.Pointer()
    if bMethPtr == 0 {
        fmt.Println("No implementation")
    } else {
        fmt.Println("Implementation found")
    }
} else {
    fmt.Println("Interface not embedded")
}
ログイン後にコピー

関数へのポインターが 0 の場合、関数は存在しません。 実装。それ以外の場合は、実装が存在します。

代替アプローチ

より単純なアプローチも使用できます:

if b.A != nil {
    b.Foo()
}
ログイン後にコピー

組み込みインターフェースが設定されている場合nil に設定すると、b.Foo() 呼び出しがパニックになります。それ以外の場合は、実装 (存在する場合) が実行されます。

以上がGo 構造体の埋め込みインターフェイスにリフレクションを使用した関数実装があるかどうかを確実に検出するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート