反射

反射 #

反射包名为reflect

func TypeOf(i interface{}) Type
reflect.TypeOf(任意类型变量) 返回反射的reflect.Type接口类型
    var x float64 = 3.4
    reflect.TypeOf(x).String() 等价 reflect.TypeOf(x).Name()
    fmt.Println("type:", reflect.TypeOf(x).String()) //type: float64

func ValueOf(i interface{}) Value
reflect.ValueOf(变量名) 返回反射的reflect.Value结构体类型,用途:获取和设置变量的值
    var x float64 = 3.4
    fmt.Println("type:", reflect.ValueOf(x).Float()) //type: 3.4
    v := reflect.ValueOf(x)
    fmt.Println("type:", v.Type()) //type: float64
    fmt.Println("kind is float64:", v.Kind() == reflect.Float64) //kind is float64: true
    fmt.Println("value:", v.Float()) //value: 3.4

reflect.Type接口方法 #

type Type interface {
	//
	Align() int
	//
	FieldAlign() int
	//获取第i个方法并返回reflect.Method结构体对象
	Method(int) Method
	//
	MethodByName(string) (Method, bool)
	//获取结构体中方法个数
	NumMethod() int
	//获取值类型名称,如int,string,bool,[]int等,等价 String()
	Name() string
	//
	PkgPath() string
	//
	Size() uintptr
	//获取值类型名称,如int,string,bool,[]int等,等价 Name()
	String() string

	//返回反射出来的值类型名,种类, Kind类型是unit类型:type Kind uint
	Kind() Kind
	//
	Implements(u Type) bool

	//
	AssignableTo(u Type) bool

	//
	ConvertibleTo(u Type) bool

	//
	Comparable() bool

	//
	Bits() int

	//
	ChanDir() ChanDir

	//
	IsVariadic() bool
	//取指针类型的元素类型,返回Type接口类型 It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
	Elem() Type

	//i表示获取第i个成员,从0开始,返回StructField结构体对象
	Field(i int) StructField
	//通过索引获取成员的StructField结构体对象
	FieldByIndex(index []int) StructField
	//通过结构体的字段名(即成员名)获取返回StructField结构体对象,第2个返回参数表示是否存在该字段名
	FieldByName(name string) (StructField, bool)

	//
	FieldByNameFunc(match func(string) bool) (StructField, bool)

	//
	In(i int) Type

	//
	Key() Type

	//
	Len() int

	//结构体中的字段个数(即成员个数)
	NumField() int

	//
	NumIn() int

	//
	NumOut() int

	//
	Out(i int) Type

	common() *rtype
	uncommon() *uncommonType
}

reflect.Method内置结构体对象如下:
    type Method struct {
        Name    string //方法名
        PkgPath string
        Type  Type  //方法类型,返回reflect.Type接口对象
        Func  Value //
        Index int   //在Type.Method结构体中的索引
    }
更多文档: https://golang.google.cn/pkg/reflect/#Type

func New(typ Type) Value 把reflect.Type接口对象转reflect.Value结构体对象
示例:
    var x float64 = 4.4
	xType := reflect.TypeOf(x)
	//输出:*float64 ptr
	fmt.Println(reflect.New(xType).Type(), reflect.New(xType).Kind())

reflect.Value结构体支持的方法 #

返回reflect.Value结构体类型,用途:获取和设置变量的值
func ValueOf(i interface{}) Value
reflect.Value结构体支持的方法如下:
  func (v Value) Type() Type 把reflect.Value对象转reflect.Type结构体对象
  func (v Value) Interface() (i interface{}) 获取变量值
  func (v Value) CanInterface() bool
  func (v Value) Kind() Kind 返回种类,type Kind uint
  func (v Value) Elem() Value 取值指向的元素值
  func (v Value) Addr() Value 对可寻址的值返回其地址,类似于语言层& 操作。当值不可寻址时发生宕机
  func (v Value) CanAddr() bool 表示值是否可寻址
  func (v Value) UnsafeAddr() uintptr
  func (v Value) String() string 将值以字符串类型返回,原变量值是字符串才可以
  func (v Value) Bool() bool 将值以 bool 类型返回,原变量值是布尔型才可以
  func (v Value) Int() int64 将值以 int64 类型返回,原变量值是int型才可以
  func (v Value) Uint() uint64
  func (v Value) Float() float64
  func (v Value) IsNil() bool 判断值是否为nil
  func (v Value) IsValid() bool 判断值是否有效
  func (v Value) Index(i int) Value
  func (v Value) Bytes() []byte 将值以字节数组 []bytes 类型返回
  func (v Value) runes() []rune
  func (v Value) Call(in []Value) []Value
  func (v Value) CallSlice(in []Value) []Value
  func (v Value) Cap() int
  func (v Value) Close()
  func (v Value) Complex() complex128
  func (v Value) Convert(t Type) Value
  func (v Value) NumField() int 结构体中的字段个数(即成员个数)
  func (v Value) Field(i int) Value 根据索引获取字段对象并返回reflect.Value结构体对象
  func (v Value) FieldByIndex(index []int) Value
  func (v Value) FieldByName(name string) Value 通过结构体字段名获取字段对象并返回reflect.Value结构体对象
  func (v Value) FieldByNameFunc(match func(string) bool) Value
  func (v Value) Len() int
  func (v Value) MapIndex(key Value) Value
  func (v Value) MapKeys() []Value
  func (v Value) NumMethod() int 返回方法个数
  func (v Value) Method(i int) Value 获取第i个方法并返回reflect.Value结构体对象,下标从0开始算
  func (v Value) MethodByName(name string) Value
  func (v Value) OverflowComplex(x complex128) bool
  func (v Value) OverflowFloat(x float64) bool
  func (v Value) OverflowInt(x int64) bool
  func (v Value) OverflowUint(x uint64) bool
  func (v Value) Pointer() uintptr
  func (v Value) Recv() (x Value, ok bool)
  func (v Value) TryRecv() (x Value, ok bool)
  func (v Value) Send(x Value)
  func (v Value) TrySend(x Value) bool
  func (v Value) CanSet() bool 判断值是否能被修改
  func (v Value) Set(x Value)
  func (v Value) SetBool(x bool)
  func (v Value) SetBytes(x []byte)
  func (v Value) SetCap(n int)
  func (v Value) SetComplex(x complex128)
  func (v Value) SetFloat(x float64)
  func (v Value) SetInt(x int64)
  func (v Value) SetUint(x uint64)
  func (v Value) SetString(x string)
  func (v Value) SetLen(n int)
  func (v Value) SetMapIndex(key, val Value)
  func (v Value) SetPointer(x unsafe.Pointer)
  func (v Value) Slice(i, j int) Value
  func (v Value) Slice3(i, j, k int) Value


更多文档:https://golang.google.cn/pkg/reflect/#Value
示例1:
    Abc := 97
    refVal := reflect.ValueOf(Abc)
    fmt.Println(refVal.Type().Name(), refVal.Kind()) //int int
示例2:
    abc := "hello"
    refVal := reflect.ValueOf(abc)
    fmt.Println(refVal.Interface()) //hello

reflect包内置类型常量 #

类型归属的种类(Kind)使用的是 reflect.Type接口中的 Kind() 方法获取
type Kind uint
const (
	Invalid Kind = iota  //非法类型
	Bool //布尔类型
	Int  //有符号整型
	Int8 //有符号8位整型
	Int16 //有符号16位整型
	Int32
	Int64
	Uint  //无符号整型
	Uint8 //无符号8位整型
	Uint16
	Uint32
	Uint64
	Uintptr //指针
	Float32
	Float64
	Complex64
	Complex128
	Array //数组
	Chan  //通道、信道
	Func  //函数
	Interface //接口
	Map  //映射,map类型
	Ptr  //指针
	Slice //切片
	String
	Struct //结构体
	UnsafePointer //底层指针
)
更多文档:https://golang.google.cn/pkg/reflect/#Kind
示例:
    fmt.Println(reflect.TypeOf([]int{1,2}).Kind()) //slice
    if reflect.TypeOf([]int{1,2}).Kind()==reflect.Slice {
        fmt.Println("是切片类型")
    }

反射包内置结构体:reflect.StructField结构体 #

type StructField struct {
	//结构体的字段名
	Name string
	//字段路径
	PkgPath string
	Type      Type      //字段反射类型对象,即reflect.Type接口对象
	Tag       StructTag //字段的结构体标签,为结构体字段标签的额外信息,字符串类型值,type StructTag string
	Offset    uintptr   //字段在结构体中的相对偏移
	Index     []int     //Type.FieldByIndex返回的索引值
	Anonymous bool      //是否为匿名字段
}
备注:
    结构体的标签格式写法:`key1:"value1" key2:"value2"`
    示例:type cat struct {
       		Name string
       		Age int `json:"age" id:"100"`
       	}
StructTag结构体支持的方法如下:
func (tag StructTag) Get(key string) string 入参为tag名(如key1)返回值为key1对应的值如value1,key1不存在返回空
func (tag StructTag) Lookup(key string) (value string, ok bool) 入参为tag名(如key1)返回值为key1对应的值如value1,第2个返回值判断是否存在key1

反射示例1 #

package main
import (
	"fmt"
	"reflect"
)
func main()  {
	// 声明一个猫结构体
	type cat struct {
		//名称
		Name string
		// 带有结构体tag的字段
		Age int `json:"age" id:"100"`
	}
	// 创建cat的实例
	ins := cat{Name: "mimi", Age: 18}
	//反射结构体实例返回reflect.Type接口对象
	typeOfCat := reflect.TypeOf(ins)
	//遍历结构体所有成员
	for i := 0; i < typeOfCat.NumField(); i++ {
		//获取第i个成员的结构体字段类型(即reflect.StructField结构体对象)
		fieldType := typeOfCat.Field(i)
		tmpKind := fieldType.Type.Kind() //值类型
		//打印成员信息:名称和tag
		fmt.Printf("成员名: %v  tag: '%v' 索引:%#v 类型:%v json_tag:%v\n",
                fieldType.Name, fieldType.Tag, fieldType.Index,tmpKind,fieldType.Tag.Get("json"))

	}
}
输出结果如下:
成员名: Name  tag: '' 索引:[]int{0} 类型:string json_tag:
成员名: Age  tag: 'json:"age" id:"100"' 索引:[]int{1} 类型:int json_tag:age

反射示例2 #

package main
import (
	"fmt"
	"reflect"
	"strings"
	"time"
)
type xyz struct {
	Age string
}
func (x *xyz) Hi()  {
}
func main()  {
	abc := "hi"
	DebugPrintReflect(abc)
	DebugPrintReflect(time.Hour)
	DebugPrintReflect(&xyz{})
}
func DebugPrintReflect(x interface{}) {
	v := reflect.ValueOf(x) //反射,返回reflect.Value结构体对象
	t := v.Type() //返回reflect.Type接口对象
	fmt.Printf("类型为 %s,类型支持的方法如下:\n", t)
	for i := 0; i < v.NumMethod(); i++ {
		methType := v.Method(i).Type() //具体某个方法转成reflect.Type接口对象
		fmt.Printf("func (%s) %s%s\n", t, t.Method(i).Name,
			strings.TrimPrefix(methType.String(), "func"))
	}
}
Build by Loppo 0.6.15