[golang]golang reflect详细用法整理
2014-11-09 19:55
253 查看
本博客原创博文版权所有 @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 [2]Go 数据结构:接口
/article/3468278.html
[3]Reflect OfGolang http://wendal.net/2012/1130.html [4]golang的反射-Value
/article/5181891.html
[5]无闻:【Go编程基础】13反射reflection|Go视频教程|Go语言基础教程 http://www.56.com/w41/play_album-aid-11263603_vid-OTMxNzUyOTc.html
本博客原创博文版权所有 @Allyvipally@gmail.com
仅供交流学习使用用于商业用途请联系原作者
转载请注明出处:http://blog.sina.com.cn/ally2014
仅供交流学习使用用于商业用途请联系原作者
转载请注明出处: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 [2]Go 数据结构:接口
/article/3468278.html
[3]Reflect OfGolang http://wendal.net/2012/1130.html [4]golang的反射-Value
/article/5181891.html
[5]无闻:【Go编程基础】13反射reflection|Go视频教程|Go语言基础教程 http://www.56.com/w41/play_album-aid-11263603_vid-OTMxNzUyOTc.html
本博客原创博文版权所有 @Allyvipally@gmail.com
仅供交流学习使用用于商业用途请联系原作者
转载请注明出处:http://blog.sina.com.cn/ally2014
相关文章推荐
- golang 中 reflect 简单用法
- java类vector的详细用法整理
- vi 编辑器的用法(超详细的资料整理)
- Dephi 程序输入法自动切换最简单最好用的实现方法(被程序员杂志采纳,重新详细整理)
- 最详细的SQL注入相关的命令整理
- Norton Ghost批处理命令用法详细介绍
- PING命令的详细用法
- 最详细的SQL注入相关的命令整理
- adodb Stream 详细用法 选择自 3cts 的 Blog
- 转贴GDB的详细用法
- 在DOS下的DEBUG命令的详细用法
- adodb Stream 详细用法
- Windows Xp修复控制台详细用法
- #ifndef#define#endif的用法(整理)
- 无间断滚动marquee的详细用法解析
- 最详细的SQL注入相关的命令整理
- java.util.vector中的vector的详细用法
- WebClient的详细用法
- 无间断滚动marquee的详细用法解析
- marquee的详细用法解析