Heim  >  Artikel  >  Backend-Entwicklung  >  Bestimmen Sie, ob das Schnittstellentypfeld der Struktur festgelegt ist

Bestimmen Sie, ob das Schnittstellentypfeld der Struktur festgelegt ist

PHPz
PHPznach vorne
2024-02-09 18:27:08658Durchsuche

Bestimmen Sie, ob das Schnittstellentypfeld der Struktur festgelegt ist

Der PHP-Editor Xiaoxin ist hier, um einen Trick zu verraten, mit dem Sie feststellen können, ob das Schnittstellentypfeld von struct festgelegt ist. In der Go-Sprache kann der Strukturtyp mehrere Schnittstellen implementieren. Indem wir feststellen, ob das Feld „Schnittstellentyp“ festgelegt ist, können wir leicht feststellen, ob eine Struktur eine bestimmte Schnittstelle implementiert. Diese Technik ist sehr praktisch. Sie kann den Objekttyp im Code genau bestimmen und entsprechend behandeln. Schauen wir uns als Nächstes die spezifische Implementierungsmethode an!

Frageninhalt

Gegeben sei eine Struktur, deren Felder zum Schnittstellentyp gehören:

type a interface { foo() }
type b interface { bar() }

type container struct {
   fielda a
   fieldb b
   ...
}

Und die Strukturen, die diese Schnittstellen implementieren:

type a struct {}
func (*a) foo() {}
func newa() *a { return &a{} }

type b struct {}
func (*b) bar() {}
func newb() *b { return &b{} }

Und der Code, der die container-Instanz erstellt, ohne explizit alle Felder festzulegen:

c := &container{}
c.fielda = newa()
// c.fieldb = newb()  // <-- fieldb not explicitly set

Wie kann ich mithilfe von Reflektion ein Feld erkennen, das nicht explizit festgelegt ist?

Überprüfen Sie den Wert von fieldb zur Laufzeit, vscode meldet den Wert gerne als nil. Ebenso kommt es beim Versuch, c.fieldb.bar() aufzurufen, aufgrund einer Null-Zeiger-Dereferenzierung zu einer Panik. Aber durch Reflexion können Sie isnil nicht testen, noch gibt iszero true zurück:

func validateContainer(c *container) {
    tC := reflect.TypeOf(*c)
    for i := 0; i < tC.NumField(); i++ {
        reflect.ValueOf(tC.Field(i)).IsNil() // panics
        reflect.ValueOf(tC.Field(i)).IsZero() // always false
        reflect.ValueOf(tC.Field(i)).IsValid() // always true
    }
}

Lösung

Sie sollten nachsehen reflect.valueof(*c) 的字段,而不是 reflect.typeof(*c).

package main

import (
    "fmt"
    "reflect"
)

func validatecontainer(c *container) {
    tc := reflect.typeof(*c)
    vc := reflect.valueof(*c)
    for i := 0; i < vc.numfield(); i++ {
        if f := vc.field(i); f.kind() == reflect.interface {
            fmt.printf("%v: isnil: %v, iszero: %v, isvalid: %v\n",
                tc.field(i).name,
                f.isnil(),
                f.iszero(),
                f.isvalid(),
            )
        }
    }

    // tc.field(i) returns a reflect.structfield that describes the field.
    // it's not the field itself.
    fmt.printf("%#v\n", reflect.valueof(tc.field(0)))
}

type a interface{ foo() }
type b interface{ bar() }

type container struct {
    fielda a
    fieldb b
}

type a struct{}

func (*a) foo() {}
func newa() *a  { return &a{} }

func main() {
    c := &container{}
    c.fielda = newa()
    validatecontainer(c)
}

Ausgabe:

FieldA: IsNil: false, isZero: false, IsValid: true
FieldB: IsNil: true, isZero: true, IsValid: true
reflect.StructField{Name:"FieldA", PkgPath:"", Type:(*reflect.rtype)(0x48de20), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:false}

Das obige ist der detaillierte Inhalt vonBestimmen Sie, ob das Schnittstellentypfeld der Struktur festgelegt ist. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen