[golang]golang reflect详细用法整理

本博客原创博文版权所有 @Allyvipally@gmail.com
仅供交流学习使用用于商业用途请联系原作者 
转载请注明出处:http://blog.sina.com.cn/ally2014
 
最近在尝试用Go写一些东西,发现Go不支持泛型确实是一件比较蛋疼的事,同样功能的一个类,只有底层数据结构有一点点差异,需要实现N遍。特别像我这种在C++世界挣扎也纠结了很多年,用惯了模板编程思想的程序猿。好在Golang提供了reflect机制,可以在一定程度上满足对泛型编程的一些需求。
想实现的一些需求:
1.通过类型字符串动态创建类型对象
2.动态的调用一些预定义函数,而不需要依赖实现该函数的package
3.实现一些通用的数据结构,比如像C++ STL那样的泛型容器
4.一些特定类型的检查和操作 如chan Type,[]Type
5...
 
//---------------------------------以下是用reflect实现一些类型无关的泛型编程示例
//new object same the type as sample
func New(sample interface{}) interface{} {
      t :=reflect.ValueOf(sample).Type()
      v :=reflect.New(t).Interface()
      returnv
}
//---------------------------------check type of aninterface
func CheckType(val interface{}, kind reflect.Kind) bool {
      v :=reflect.ValueOf(val)
      return kind== v.Kind()
}
//---------------------------------if _func is not a functionor para num and type not match,it will cause panic
func Call(_func interface{}, params ...interface{}) (result[]interface{}, err error) {
      f :=reflect.ValueOf(_func)
      iflen(params) != f.Type().NumIn() {
              ss := fmt.Sprintf("The number of params is not adapted.%s",f.String())
              panic(ss)
              return
      }
      var in[]reflect.Value
      iflen(params) > 0 { //prepare in paras
              in = make([]reflect.Value, len(params))
              for k, param := range params {
                      in[k] = reflect.ValueOf(param)
              }
      }
      out :=f.Call(in)
      if len(out)> 0 { //prepare out paras
              result = make([]interface{}, len(out), len(out))
              for i, v := range out {
                      result[i] = v.Interface()
              }
      }
      return
}
//---------------------------------if ch is not channel,itwill panic
func ChanRecv(ch interface{}) (r interface{}) {
      v :=reflect.ValueOf(ch)
      if x, ok :=v.Recv(); ok {
              r = x.Interface()
      }
      return
}
//---------------------------------reflect fields of astruct
func reflect_struct_info(it interface{}) {
      t :=reflect.TypeOf(it)
      fmt.Printf("interface info:%s %s %s %s\n", t.Kind(), t.PkgPath(),t.Name(), t)
      if t.Kind()== reflect.Ptr { //if it is pointer, get it element type
              tt := t.Elem()
              if t.Kind() == reflect.Interface {
                      fmt.Println(t.PkgPath(), t.Name())
                      for i := 0; i < tt.NumMethod(); i++ {
                              f := tt.Method(i)
                              fmt.Println(i, f)
                      }
              }
      }
      v :=reflect.ValueOf(it)
      k :=t.Kind()
      if k ==reflect.Ptr {
              v = v.Elem() //指针转换为对应的结构
              t = v.Type()
              k = t.Kind()
      }
      fmt.Printf("value type info:%s %s %s\n", t.Kind(), t.PkgPath(),t.Name())
      if k ==reflect.Struct { //反射结构体成员信息
              for i := 0; i < t.NumField(); i++ {
                      f := t.Field(i)
                      fmt.Printf("%s %v\n", i, f)
              }
              for i := 0; i < t.NumMethod(); i++ {
                      f := t.Method(i)
                      fmt.Println(i, f)
              }
              fmt.Printf("Fileds:\n")
              f := v.MethodByName("func_name")
              if f.IsValid() { //执行某个成员函数
                      arg := []reflect.Value{reflect.ValueOf(int(2))}
                      f.Call(arg)
              }
              for i := 0; i < v.NumField(); i++ {
                      f := v.Field(i)
                      if !f.CanInterface() {
                              fmt.Printf("%d:[%s] %v\n", i, t.Field(i), f.Type())
                              continue
                      }
                      val := f.Interface()
                      fmt.Printf("%d:[%s] %v %v\n", i, t.Field(i), f.Type(), val)
              }
              fmt.Printf("Methods:\n")
              for i := 0; i < v.NumMethod(); i++ {
                      m := v.Method(i)
                      fmt.Printf("%d:[%v] %v\n", i, t.Method(i), m)
              }
      }
}
//---------------------------------以下是本人对goreflect的一些理解不正之处欢迎指正
Go reflect对go的底层数据结构抽象大概可以定义成如下:
type reflectKind int
type reflectStructField struct {
      reflectValue
      Name      string
      PkgPathstring
      Type          reflectType// field type
      Tag            StructTag // field tag string
      Offset      uintptr    // offset withinstruct, in bytes
      Index        []int        // index sequence for Type.FieldByIndex
      Anonymousbool          // is an embedded field
}
type reflectMethod strut{
      Name      string
      PkgPathstring
      Type  reflectType  // methodtype
      Func  Value // func with receiver as firstargument
      Indexint    // index forType.Method
}
//any go type can abstact as a reflectType
type reflectType struct {
      Kind      reflectKind
      Name      string
      PkgPathstring
      Fields  []reflectType
      Methods[]reflectMethod
}
//every go value(with any go type) can abstact as areflectValue
type reflectValue struct {
      Type    reflectType
      Value  unsafePointer
      Fields[]reflectStructField
      SpecificValueOpers()
}
//----------------------------------------------an imagined type inGO
type GoType struct {
      reflectType
      reflectValue
}
//---------------------------------------------- 
...未完待续
 
附:package reflect包类型函数说明
func Copy(dst, src Value) int
func DeepEqual(a1, a2 interface{}) bool
func Select(cases []SelectCase) (chosen int, recv Value, recvOKbool)
type ChanDir
func (d ChanDir) String() string
type Kind
      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
      )
      func (kKind) String() string
type Method
type SelectCase
type SelectDir
type SliceHeader
type StringHeader
type StructField
type StructTag
func (tag StructTag) Get(key string) string
type Type
      funcChanOf(dir ChanDir, t Type) Type
      funcMapOf(key, elem Type) Type
      func PtrTo(tType) Type
      funcSliceOf(t Type) Type
      funcTypeOf(i interface{}) Type
type Value
      funcAppend(s Value, x ...Value) Value
      funcAppendSlice(s, t Value) Value
      funcIndirect(v Value) Value
      funcMakeChan(typ Type, buffer int) Value
      funcMakeFunc(typ Type, fn func(args []Value) (results []Value))Value
      funcMakeMap(typ Type) Value
      funcMakeSlice(typ Type, len, cap int) Value
      func New(typType) Value
      funcNewAt(typ Type, p unsafe.Pointer) Value
      funcValueOf(i interface{}) Value
      funcZero(typ Type) Value
      func (vValue) Addr() Value
      func (vValue) Bool() bool
      func (vValue) Bytes() []byte
      func (vValue) Call(in []Value) []Value
      func (vValue) CallSlice(in []Value) []Value
      func (vValue) CanAddr() bool
      func (vValue) CanInterface() bool
      func (vValue) CanSet() bool
      func (vValue) Cap() int
      func (vValue) Close()
      func (vValue) Complex() complex128
      func (vValue) Convert(t Type) Value
      func (vValue) Elem() Value
      func (vValue) Field(i int) Value
      func (vValue) FieldByIndex(index []int) Value
      func (vValue) FieldByName(name string) Value
      func (vValue) FieldByNameFunc(match func(string) bool) Value
      func (vValue) Float() float64
      func (vValue) Index(i int) Value
      func (vValue) Int() int64
      func (vValue) Interface() (i interface{})
      func (vValue) InterfaceData() [2]uintptr
      func (vValue) IsNil() bool
      func (vValue) IsValid() bool
      func (vValue) Kind() Kind
      func (vValue) Len() int
      func (vValue) MapIndex(key Value) Value
      func (vValue) MapKeys() []Value
      func (vValue) Method(i int) Value
      func (vValue) MethodByName(name string) Value
      func (vValue) NumField() int
      func (vValue) NumMethod() int
      func (vValue) OverflowComplex(x complex128) bool
      func (vValue) OverflowFloat(x float64) bool
      func (vValue) OverflowInt(x int64) bool
      func (vValue) OverflowUint(x uint64) bool
      func (vValue) Pointer() uintptr
      func (vValue) Recv() (x Value, ok bool)
      func (vValue) Send(x Value)
      func (vValue) Set(x Value)
      func (vValue) SetBool(x bool)
      func (vValue) SetBytes(x []byte)
      func (vValue) SetComplex(x complex128)
      func (vValue) SetFloat(x float64)
      func (vValue) SetInt(x int64)
      func (vValue) SetLen(n int)
      func (vValue) SetMapIndex(key, val Value)
      func (vValue) SetPointer(x unsafe.Pointer)
      func (vValue) SetString(x string)
      func (vValue) SetUint(x uint64)
      func (vValue) Slice(beg, end int) Value
      func (vValue) String() string
      func (vValue) TryRecv() (x Value, ok bool)
      func (vValue) TrySend(x Value) bool
      func (vValue) Type() Type
      func (vValue) Uint() uint64
      func (vValue) UnsafeAddr() uintptr
type ValueError
func (e *ValueError) Error() string
 
以下是学习Golang reflect的过程中参考到的一些比较有价值的相关资源连接
[1] GoLang反射的规则
http://www.tuicool.com/articles/7NjaQn
http://my.oschina.net/Obahua/blog/160458
http://wendal.net/2012/1130.html
http://www.cnblogs.com/zhepama/archive/2013/04/12/3017204.html
http://www.56.com/w41/play_album-aid-11263603_vid-OTMxNzUyOTc.html

本博客原创博文版权所有 @Allyvipally@gmail.com
仅供交流学习使用用于商业用途请联系原作者 
转载请注明出处:http://blog.sina.com.cn/ally2014
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言中的reflect包提供了一种对程序的静态类型进行操作的方法,即可以在程序运行时动态地调用、检查和更改变量、类型和方法。 首先,reflect包提供了两个重要的类型:Type和Value。Type表示变量的类型,Value则表示变量的值。可以通过reflect.TypeOf和reflect.ValueOf来获取一个变量的Type和Value。 使用reflect包,我们可以在运行时获取变量的类型和值的一些基本信息,例如判断一个变量是否是某个特定类型,或者获取一个变量的名称和值。这在某些情况下可能是非常有用的,比如在编写通用的函数时,需要对不同类型的变量做相同的处理。 此外,reflect包还提供了一些函数来获取、设置和调用变量、类型和方法的具体信息。可以使用reflect.Value的相关方法来获取和设置变量的值,也可以使用reflect.Type的相关方法来获取类型的信息。使用reflect包还可以动态地调用某个值的方法。 需要注意的是,使用reflect包可能会导致一些性能上的损失,因为在运行时需要通过反射来获取变量的信息。因此,在性能要求较高的场景下,尽量避免使用反射。 总结而言,reflect包为我们提供了一种在运行时对变量、类型和方法进行操作的方法,可以通过反射来获取、设置和调用它们的信息。但是,需要注意在性能要求较高的情况下,尽量避免使用反射。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值