go reflect、go语言的反射应用实例与分析

反射 reflection 特性描述

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

reflect 包涉及到源码文件

$GOPATH/src/reflect/value.go && type.go 文件,下面例子中调用API函数如下。

// Two Type values are equal if they represent identical types.
type Type interface {
        // Methods applicable to all types.
		
		 // lexicographic order.
        Method(int) Method
		// For an interface type, the returned Method's Type field gives the
        // method signature, without a receiver, and the Func field is nil.
        MethodByName(string) (Method, bool)
        // NumMethod returns the number of exported methods in the type's method set.
        NumMethod() int
		// NumMethod returns the number of exported methods in the type's method set.
        NumMethod() int

        // Name returns the type's name within its package for a defined type.
        // For other (non-defined) types it returns the empty string.
        Name() string

        // PkgPath returns a defined type's package path, that is, the import path
        // that uniquely identifies the package, such as "encoding/base64".
        // If the type was predeclared (string, error) or not defined (*T, struct{},
        // []int, or A where A is an alias for a non-defined type), the package path
        // will be the empty string.
        PkgPath() string

		// Kind returns the specific kind of this type.
        Kind() Kind
		// IsVariadic panics if the type's Kind is not Func.
        IsVariadic() bool

        // Elem returns a type's element type.
        // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
        Elem() Type

        // Field returns a struct type's i'th field.
        // It panics if the type's Kind is not Struct.
        // It panics if i is not in the range [0, NumField()).
        Field(i int) StructField

        // FieldByIndex returns the nested field corresponding
        // to the index sequence. It is equivalent to calling Field
        // successively for each index i.
        // It panics if the type's Kind is not Struct.
        FieldByIndex(index []int) StructField

        // FieldByName returns the struct field with the given name
        // and a boolean indicating if the field was found.
        FieldByName(name string) (StructField, bool)
		
        // NumField returns a struct type's field count.
        // It panics if the type's Kind is not Struct.
        NumField() int

        // NumIn returns a function type's input parameter count.
        // It panics if the type's Kind is not Func.
        NumIn() int

        // NumOut returns a function type's output parameter count.
        // It panics if the type's Kind is not Func.
        NumOut() int

        // Out returns the type of a function type's i'th output parameter.
        // It panics if the type's Kind is not Func.
        // It panics if i is not in the range [0, NumOut()).
        Out(i int) Type

        common() *rtype
        uncommon() *uncommonType
}

响应的方法源码,请读者自行查看源码。

实例1

package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Id int
	Name string
	Age int
}

func (user User) hello() {
	fmt.Println("hello world")
}

func main() {
	u := User{2, "zhangsan", 22}
	Info(u)
}

func Info(o interface{}) {
	t := reflect.TypeOf(o)
	fmt.Println("Type: ", t.Name())

	if K := t.Kind(); K != reflect.Struct{
		fmt.Println("传入的类型不对,需用传对象或者基本数据类型的地址值")
		return
	}

	v := reflect.ValueOf(o)
	fmt.Println("field: ")
	for i :=0; i < t.NumField(); i++ {
		f := t.Field(i)
		val := v.Field(i).Interface()
		fmt.Printf("%6s: %v = %v \n",f.Name, f.Type, val)
	}

	for i :=0; i < t.NumMethod(); i++ {
		m := t.Method(i)
		fmt.Printf("%6s: %v \n", m.Name, m.Type)
	}
}

运行结果

~/gomod/reflect$ go run reflect.go 
Type:  User
field: 
    Id: int = 2 
  Name: string = zhangsan 
   Age: int = 22 

实例2

package main
import (
	"fmt"
	"reflect"
)

type User struct {
	Id int
	Name string
	Age int
}

func (u User) Hello(name string){
	fmt.Println("hello method:", name,",say my name is",u.Name)
}

func main() {
	u := User{1,"hale",22}
	v := reflect.ValueOf(u)

	//get object hello method
	mv := v.MethodByName("Hello")
	// make slice
	args := []reflect.Value{reflect.ValueOf("jay")}
	// 
	mv.Call(args)
}

运行结果

/gomod/src/reflect$ go run reflect1.go 
hello method: jay ,say my name is hale
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值