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!
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 } }
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!