[golang]golang reflect詳細用法整理

本博客原創博文版權所有 @[email protected]
僅供交流學習使用用於商業用途請聯繫原作者 
轉載請註明出處: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)
   
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章