golang的reflection(转)(一)

让人想犯罪 __ 提交于 2020-03-17 02:01:18

某厂面试归来,发现自己落伍了!>>>

反射reflection

  • 可以大大提高程序的灵活性,使得interface{}有更大的发挥余地
  • 反射可以使用TypeOf和ValueOf函数从接口中获取目标对象信息
  • 反射会将匿名字段作为独立字段(匿名字段的本质)
  • 想要利用反射修改对象状态,前提是interface.data是settable,即pointer-interface
  • 通过反射可以“动态”调用方法

常用的类型、函数和方法

//返回动态类型i的类型,如果i是一个空结构体类型,TypeOf将返回nil
func TypeOf(i interface{}) Type

//Type 接口类型
type Type interface {
    Align() int
    FieldAlign() int
    //指定结构体中方法的下标,返回某个方法的对象,需要注意的是返回的Method是一个独立的结构体
    Method(int) Method
    /*
    type Method struct {
        Name string
        PkgPath string
        Type Type
        Func Value
        Index int
    }
    */


    MethodByName(string) (Method, bool)

    //返回该结构体类型的方法下标
    NumMethod() int
    //返回类型的名称,即动态类型i的名称
    Name() string
    PkgPath() string
    Size() uintptr
    String() string
    Kind() Kind
    Implements(u Type) bool
    AssignableTo(u Type) bool
    ConvertibleTo(u Type) bool
    Comparable() bool
    Bits() int
    ChanDir() ChanDir
    IsVariadic() bool
    Elem() Type
    //返回结构体类型第i个字段
    Field(i int) StructField
    //StructField结构体
    //type StructField struct {
    // Name string
    // PkgPath string
    // Type Type
    // Tag  StructTag
    // Offset uintptr
    // Index []int
    // Anonymous bool

    //根据结构体字段索引获取嵌入字段的结构体信息
    FieldByIndex(index []int) StructField

    FieldByName(name string) (StructField, bool)
    FieldByNameFunc(match func(string) bool) (StructField, bool)
    In(i int) Type
    Key() Type
    Len() int
    //返回动态类型i(结构体字段)的字段总数
    NumField() int
    NumIn() int
    NumOut() int
    Out(i int) Type
}

//返回接口i的一个初始化的新值.ValueOf(nil)返回一个零值
func ValueOf(i interface{}) Value

// Value结构体
type Value struct {

}
// Value结构体的一些方法
// 返回结构体v中的第i个字段。如果v的类型不是结构体或者i超出了结构体的范围,则会出现panic
func (v Value) Field(i int) Value

//以接口类型返回v的当前值
func (v Value) Interface() (i interface{})
//等价于.
var i interface{} = (v's underlying value)


//通过反射方式修改结构体对象的一些方法

//返回接口v包含或者指针v包含的值
func (v Value) Elem() Value
//判断该接口v是否可以被set修改
func (v Value) CanSet() bool

//使用另外一个反射接口去修改反射值
func (v Value) Set(x Value)
//其他不同类型的Set
func (v Value) SetBool(x bool)
func (v Value) SetBytes(x []byte)
func (v Value) SetFloat(x float64)
func (v Value) SetInt(x int64)
//设置结构体对象v的长度为n
func (v Value) SetLen(n int)
func (v Value) SetString(x string)


//一些辅助方法
//返回反射结构体的Value的类型.如果v为零值,IsValid将返回false
func (v Value) Kind() Kind
//判断value是否为有效值,通常用在判断某个字段是否在反射体的Value中
func (v Value) IsValid() bool

//Kind常量
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
)

 

反射的基本操作

通过反射来获取结构体字段的名称以及其他相关信息。

package main

import (
    "fmt"
    "reflect"
)

//定义结构体
type User struct {
    Id   int
    Name string
    Age  int
}

//定义结构体方法
func (u User) Hello() {
    fmt.Println("Hello xuxuebiao")
}

func main() {
    u := User{1, "bgops", 25}
    Info(u)
    u.Hello()
}

//定义一个反射函数,参数为任意类型
func Info(o interface{}) {
    //使用反射类型获取o的Type,一个包含多个方法的interface
    t := reflect.TypeOf(o)
    //打印类型o的名称
    fmt.Println("type:", t.Name())

    //使用反射类型获取o的Value,一个空的结构体
    v := reflect.ValueOf(o)
    fmt.Println("Fields:")

    //t.NumField()打印结构体o的字段个数(Id,Name,Age共三个)
    for i := 0; i < t.NumField(); i++ {
        //根据结构体的下标i来获取结构体某个字段,并返回一个新的结构体
        /**
        type StructField struct {
            Name string
            PkgPath string
            Type      Type
            Tag       StructTag
            Of
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!