"反射結構體"是指在程序執行時,遍歷結構體中的字段以及方法。
1.反射結構體
下面使用一個簡單的例子說明如何反射結構體。
定義一個結構體,包括3個字段,以及一個方法。
通過reflect包,首先查看這個結構體對應的動態類型reflect.Type
和動態值reflect.Value
,並查看這個結構體對應的基本類型。
接着查看結構體的字段數量,並遍歷每個字段。
打印每個字段的類型、值、以及tag標簽。
最后,調用結構體中的方法,並打印返回結果。
具體代碼如下。
package main
import (
"fmt"
"reflect"
)
type Orange struct {
size int `kitty:"size"`
Weight int `kitty:"wgh"`
From string `kitty:"source"`
}
func (this Orange) GetWeight() int {
return this.Weight
}
func main(){
orange := Orange{1, 18, "Shanghai"}
refValue := reflect.ValueOf(orange) // value
refType := reflect.TypeOf(orange) // type
fmt.Println("orange refValue:", refValue)
fmt.Println("orange refType:", refType)
orangeKind := refValue.Kind() // basic type
fmt.Println("orange Kind:", orangeKind)
fieldCount := refValue.NumField() // field count
fmt.Println("fieldCount:", fieldCount)
for i:=0; i < fieldCount; i++{
fieldType := refType.Field(i) // field type
fieldValue := refValue.Field(i) // field vlaue
fieldTag := fieldType.Tag.Get("kitty") // field tag
fmt.Println("fieldTag:", fieldTag)
fmt.Println("field type:", fieldType.Type)
fmt.Println("fieldValue:", fieldValue)
}
// method
result := refValue.Method(0).Call(nil)
fmt.Println("method result:", result[0])
}
輸出結果:
orange refValue: {1 18 Shanghai}
orange refType: main.Orange
orange Kind: struct
fieldCount: 3
fieldTag: size
field type: int
fieldValue: 1
fieldTag: wgh
field type: int
fieldValue: 18
fieldTag: source
field type: string
fieldValue: Shanghai
method result: 18
另外, 如果反射時,使用的參數是結構體指針:
refValue := reflect.ValueOf(&orange) // value
則需要首先解引用指針,取得指針指向的對象:
refValue = refValue.Elem()
2.相關函數說明
2.1 Value.Kind()
func (v Value) Kind() Kind
其返回值為Kind
,表示golang語言自身定義的基本類型:
type Kind uint
取值包括:
const (
Invalid Kind = iota
Bool
Int
Int8
Int16
Int32
Int64
Uint
Uint8
Uint16
Uint32
Uint64
Uintptr
Float32
Float64
Complex64
Complex128
Array
Chan
Func
Interface
Map
Ptr
Slice
String
Struct
UnsafePointer
)
2.2 Value.Elem()
func (v Value) Elem() Value
方法返回v指向的對象。
要求v必須是interface或指針。
2.3 Type.Elem()
type Type Interface{
// Elem returns a type's element type.
// It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
Elem() Type
... ...
}
返回指向對象的具體類型。
要求調用者必須是Array
, Chan
, Map
, Ptr
, or Slice
。
例如,
i := 1
v := reflect.ValueOf(&i)
valueType := v.Type()
elemType := valueType.Elem()
fmt.Println("valueType:", valueType) //*int
fmt.Println("elemType:", elemType) // int
v是*int
,則element type就是int
。
例如,
sli := []string{"abc", "ef", "gh", "123"}
v := reflect.ValueOf(sli)
valueType := v.Type()
elemType := valueType.Elem()
fmt.Println("valueType:", valueType) // []string
fmt.Println("elemType:", elemType) // string
v是字符串數組,則element type就是字符串。