reflect
パッケージを使用して構造体フィールドを操作するのに苦労します。特に、フィールド値の設定方法を理解していません。
type t struct {fi int; fs string} var r t = t {123、 "jblow"} var i64 int64 = 456
フィールドiの名前の取得-これは機能しているようです
var field = reflect.TypeOf(r).Field(i).Name
フィールドiの値をa)interface {}、b)intとして取得-これは機能しているようです
var iface interface{} = reflect.ValueOf(r).Field(i).Interface()
var i int = int(reflect.ValueOf(r).Field(i).Int())
フィールドiの設定値-1つ試してください-パニック
reflect.ValueOf(r).Field(i).SetInt( i64 )
パニック:reflect.Value・非エクスポートフィールドを使用して取得した値を使用したSetInt
フィールド名「id」と「name」が気に入らなかったため、「Id」と「Name」に名前を変更しました
a)この仮定は正しいですか?
b)正しい場合、同じファイル/パッケージ内にあるため、必要ないと考えた
フィールドiの値を設定-2つ試してください(フィールド名は大文字で)-パニック
reflect.ValueOf(r).Field(i).SetInt( 465 )
reflect.ValueOf(r).Field(i).SetInt( i64 )
パニック:reflect.Value・アドレス指定不可能な値を使用したSetInt
以下の@peterSOによる指示は徹底的で高品質です
四。これは動作します:
reflect.ValueOf(&r).Elem().Field(i).SetInt( i64 )
また、フィールド名はエクスポート可能でなければならないことを文書化します(大文字で始まる)
Goは オープンソースコード として利用できます。リフレクションについて学ぶ良い方法は、Goのコア開発者がリフレクションをどのように使用しているかを確認することです。たとえば、Go fmt および json パッケージです。パッケージのドキュメントには、「パッケージファイル」という見出しの下にあるソースコードファイルへのリンクがあります。
Go jsonパッケージは、JSONをGo構造からマーシャリングおよびアンマーシャリングします。
これは、エラーを慎重に回避しながらstruct
フィールドの値を設定するステップバイステップの例です。
Go reflect
パッケージには CanAddr
関数があります。
func (v Value) CanAddr() bool
値のアドレスをAddrで取得できる場合、CanAddrはtrueを返します。このような値はアドレス可能と呼ばれます。値がスライスの要素、アドレス可能な配列の要素、アドレス可能な構造体のフィールド、またはポインターの逆参照の結果である場合、値はアドレス可能です。 CanAddrがfalseを返す場合、Addrを呼び出すとパニックになります。
Go reflect
パッケージには CanSet
関数があり、true
の場合、CanAddr
もtrue
です。
func (v Value) CanSet() bool
Vの値を変更できる場合、CanSetはtrueを返します。値は、アドレス指定可能で、エクスポートされていない構造体フィールドを使用して取得されなかった場合にのみ変更できます。 CanSetがfalseを返す場合、Setまたはタイプ固有のセッター(SetBool、SetInt64など)を呼び出すとパニックが発生します。
Set
フィールドをstruct
できることを確認する必要があります。例えば、
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
// N at start
fmt.Println(n.N)
// 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(n.N)
}
Output:
42
7
すべてのエラーチェックが不要であると確信できる場合、この例は単純化され、
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
fmt.Println(n.N)
reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7)
fmt.Println(n.N)
}
これはうまくいくようです:
package main
import (
"fmt"
"reflect"
)
type Foo struct {
Number int
Text string
}
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()))
}
プリント:
123
321