À l’aide de la reflection, comment définissez-vous la valeur d’un champ struct?

avoir du mal à travailler avec des champs de structure en utilisant le package Reflect. en particulier, n’ont pas compris comment définir la valeur du champ.

 type t struct {fi int;  fs ssortingng}
 var rt = t {123, "jblow"}
 var i64 int64 = 456
  1. obtenir le nom du champ i – cela semble fonctionner

    var field = reflect.TypeOf(r).Field(i).Name

  2. obtenir la valeur du champ i en tant que a) interface {}, b) int – cela semble fonctionner

    var iface interface{} = reflect.ValueOf(r).Field(i).Interface()

    var i int = int(reflect.ValueOf(r).Field(i).Int())

  3. réglage de la valeur du champ i – essayez-en un – panique

    reflect.ValueOf(r).Field(i).SetInt( i64 )

    panic : reflect.Value · SetInt utilisant la valeur obtenue en utilisant le champ non exporté

    en supposant qu’il n’aimait pas les noms de champs “id” et “name”, donc renommé en “Id” et “Name”

    a) cette hypothèse est-elle correcte?

    b) si correct, pensé pas nécessaire puisque dans le même fichier / paquet

  4. réglage de la valeur du champ i – essayez deux (avec les noms de champs en majuscule) – panique

    reflect.ValueOf(r).Field(i).SetInt( 465 )

    reflect.ValueOf(r).Field(i).SetInt( i64 )

    panique : reflect.Value · SetInt utilisant une valeur non adressable


Les instructions ci-dessous de @peterSO sont complètes et de haute qualité

Quatre cela marche:

reflect.ValueOf(&r).Elem().Field(i).SetInt( i64 )

il documente également que les noms de champs doivent être exportables (commencer par une majuscule)

Go est disponible en code source ouvert . Un bon moyen d’apprendre la reflection est de voir comment les principaux développeurs Go l’utilisent. Par exemple, les packages Go fmt et json . La documentation du package contient des liens vers les fichiers de code source sous l’en-tête Fichiers du package.

Le package Go json regroupe et désamorce les structures JSON depuis et vers.


Voici un exemple étape par étape qui définit la valeur d’un champ struct tout en évitant soigneusement les erreurs.

Le package Go reflect a une fonction CanAddr .

 func (v Value) CanAddr() bool 

CanAddr renvoie true si l’adresse de la valeur peut être obtenue avec Addr. Ces valeurs sont appelables. Une valeur est adressable si c’est un élément d’une tranche, un élément d’un tableau adressable, un champ d’une structure adressable ou le résultat du déréférencement d’un pointeur. Si CanAddr renvoie false, appeler Addr panique.

Le paquet Go reflect a une fonction CanSet , qui, si elle est true , implique que CanAddr est également true .

 func (v Value) CanSet() bool 

CanSet renvoie true si la valeur de v peut être modifiée. Une valeur ne peut être modifiée que si elle est adressable et n’a pas été obtenue en utilisant des champs de structure non exportés. Si CanSet renvoie false, l’appel de Set ou de tout autre régleur spécifique au type (par exemple, SetBool, SetInt64) va paniquer.

Nous devons nous assurer que nous pouvons Set le champ struct . Par exemple,

 package main import ( "fmt" "reflect" ) func main() { type t struct { N int } var n = t{42} // N at start fmt.Println(nN) // pointer to struct - addressable ps := reflect.ValueOf(&n) // struct s := ps.Elem() if s.Kind() == reflect.Struct { // exported field f := s.FieldByName("N") if f.IsValid() { // A Value can be changed only if it is // addressable and was not obtained by // the use of unexported struct fields. if f.CanSet() { // change value of N if f.Kind() == reflect.Int { x := int64(7) if !f.OverflowInt(x) { f.SetInt(x) } } } } } // N at end fmt.Println(nN) } Output: 42 7 

Si nous pouvons être certains que toutes les vérifications d’erreur sont inutiles, l’exemple simplifie

 package main import ( "fmt" "reflect" ) func main() { type t struct { N int } var n = t{42} fmt.Println(nN) reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7) fmt.Println(nN) } 

Cela semble fonctionner:

 package main import ( "fmt" "reflect" ) type Foo struct { Number int Text ssortingng } func main() { foo := Foo{123, "Hello"} fmt.Println(int(reflect.ValueOf(foo).Field(0).Int())) reflect.ValueOf(&foo).Elem().Field(0).SetInt(321) fmt.Println(int(reflect.ValueOf(foo).Field(0).Int())) } 

Impressions:

 123 321