golang 使用reflect反射结构体

"反射结构体"是指在程序执行时,遍历结构体中的字段以及方法。

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就是字符串。

你可能感兴趣的:(golang 使用reflect反射结构体)