Maison  >  Article  >  développement back-end  >  Déterminer si le champ de type d'interface de struct est défini

Déterminer si le champ de type d'interface de struct est défini

PHPz
PHPzavant
2024-02-09 18:27:08658parcourir

Déterminer si le champ de type dinterface 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 !

Contenu de la question

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

Solution

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer