方法 | 説明する |
---|---|
Field(i int) StructField | インデックスに従って、インデックスに対応する構造体フィールドの情報を返します。値が構造体でない場合、またはインデックスが範囲外の場合にクラッシュする |
NumField() int | 構造体のメンバーフィールドの数を返します。型が構造体でない場合、またはインデックスが範囲外の場合にクラッシュする |
FieldByName(name string) (StructField, bool) | 指定された文字列に従って、その文字列に対応する構造体フィールドの情報を返します。 bool は見つからない場合は false を返し、型が構造体でない場合、またはインデックスが範囲外の場合にクラッシュします。 |
FieldByIndex(index []int) StructField | 多層メンバーにアクセスする場合、[]int で提供される各構造体のフィールド インデックスに従ってフィールド情報を返します。見つからない場合はゼロを返します。型が構造体でない場合、またはインデックスが範囲外の場合にクラッシュする |
FieldByNameFunc( match func(string) bool) (StructField,bool) | 照合機能に従って必須フィールドを照合します。値が構造体でない場合、またはインデックスが範囲外の場合にクラッシュする |
構造体のフィールドタイプ
Reflect.Type の Field() メソッドは、構造体のメンバー情報を記述した StructField 構造体を返します。この情報を通じて、オフセット、インデックス、匿名かどうかなど、メンバーと構造体の関係を取得できます。フィールド、構造体タグ(Struct Tag)等があり、構造体メンバーの型情報はさらにStructFieldのTypeフィールドを通じて取得することができます。 StructField の構造は次のとおりです。
type StructField struct {
Name string // フィールド名
PkgPath string // フィールドのパッケージのパス
Type Type // フィールドのリフレクション型オブジェクト
Tag StructTag // フィールドの構造体タグ
Offset uintptr // 構造体内でのフィールドの相対オフセット
Index []int // Type.FieldByIndexで返されるインデックス値
Anonymous bool // 無名フィールドであるかどうか
}
フィールドについては以下で説明します。
- 名前: はフィールド名です。
- PkgPath: 構造内のフィールドのパス。
- Type: フィールド自体のリフレクション型オブジェクト。型はreflect.Typeで、さらにフィールドの型情報を取得できます。
- タグ: 構造体タグ。構造体フィールドタグの追加情報であり、個別に抽出できます。
- Index: FieldByIndex のインデックス順序。
- 匿名: フィールドが匿名かどうかを示します。
メンバーの反映情報を取得する
次のコードでは、構造体をインスタンス化し、その構造体メンバーを走査し、reflect.Type の FieldByName() メソッドを使用して、構造体内で指定された名前を持つフィールドを検索し、その型情報を直接取得します。
構造体のメンバーのタイプと情報への反射型アクセス:
package main
import (
"fmt"
"reflect"
)
func main() {
// 空の構造体を宣言します。
type cat struct {
Name string
// 構造体タグを持つフィールド
Type int `json:"type" id:"100"`
}
// catのインスタンスを作成します。
ins := cat{Name: "mimi", Type: 1}
// 構造体インスタンスの反射型オブジェクトを取得します。
typeOfCat := reflect.TypeOf(ins)
// 構造体のすべてのメンバーを反復処理します。
for i := 0; i < typeOfCat.NumField(); i++ {
// 各メンバーの構造体フィールドタイプを取得します。
fieldType := typeOfCat.Field(i)
// メンバー名とタグを出力します。
fmt.Printf("name: %v tag: '%v'\n", fieldType.Name, fieldType.Tag)
}
// フィールド名からフィールドタイプ情報を取得します。
if catType, ok := typeOfCat.FieldByName("Type"); ok {
// タグから必要なタグを取得します。
fmt.Println(catType.Tag.Get("json"), catType.Tag.Get("id"))
}
}
コード出力は次のとおりです。
name: Name tag: ”
name: Type tag: ‘json:”type” id:”100″‘
type 100
コードの説明は次のとおりです。
- 11 行目では、2 つのメンバーを持つ cat 構造体が宣言されています。
- 15 行目では、 Type は cat のメンバーであり、このメンバー型の後に ` で始まり
`
で終わる文字列が続きます。この文字列をGo言語ではタグと呼びます。これは通常、フィールドにカスタム情報を追加するために使用され、他のモジュールがその情報に従ってさまざまな機能を処理できるようになります。 - 19 行目では cat インスタンスを作成し、2 つのフィールドに値を割り当てます。構造タグは型情報に属し、必須ではないため割り当てることはできません。
- 22行目、インスタンスのリフレクション型オブジェクトを取得します。
- 25 行目で、reflect.Type 型の NumField() メソッドを使用して、構造体型に含まれるフィールドの数を取得します。型が構造体ではない場合、クラッシュ エラーがトリガーされます。
- 28 行目では、reflect.Type の Field() メソッドと NumField は通常、構造体のメンバーの走査操作を実装するためにペアで使用されます。
- 31 行目で、reflect.Type の Field() メソッドによって返される構造体は、reflect.Type ではなく、StructField 構造体になりました。
- 35 行目では、reflect.Type の FieldByName() を使用して、フィールド名に従って構造体フィールド情報を検索します。cat Type は返された構造体フィールド情報を示し、型は StructField で、ok は構造体フィールド情報が見つかったかどうかを示します。
- 38行目では、StructFieldのTagのGet()メソッドを使用して、Tagの名前に応じた情報を取得します。