Maison >développement back-end >Golang >Déterminer si le champ de type d'interface de struct est défini
L'éditeur PHP Xiaoxin est là pour partager une astuce pour déterminer si le champ de type d'interface de struct est défini. Dans le langage Go, le type struct peut implémenter plusieurs interfaces. En déterminant si le champ type d'interface est défini, nous pouvons facilement déterminer si une structure implémente une interface spécifique. Cette technique est très pratique. Elle permet de déterminer avec précision le type d’objet dans le code et de le gérer en conséquence. Examinons ensuite la méthode de mise en œuvre spécifique !
Étant donné une structure dont les champs appartiennent au type d'interface :
type a interface { foo() } type b interface { bar() } type container struct { fielda a fieldb b ... }
Et les structures qui mettent en œuvre ces interfaces :
type a struct {} func (*a) foo() {} func newa() *a { return &a{} } type b struct {} func (*b) bar() {} func newb() *b { return &b{} }
Et le code qui crée l'instance container
sans définir explicitement tous les champs :
c := &container{} c.fielda = newa() // c.fieldb = newb() // <-- fieldb not explicitly set
À l'aide de la réflexion, comment puis-je détecter un champ qui n'est pas défini explicitement ?
Vérifiez la valeur de fieldb au moment de l'exécution, vscode rapporte volontiers la valeur comme nil
. De même, essayer d'appeler c.fieldb.bar() paniquera en raison d'un déréférencement de pointeur nul. Mais la réflexion ne vous permet pas de tester isnil, et iszero ne renvoie pas non plus vrai :
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 } }
Tu devrais vérifier 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) }
Sortie :
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}
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!