Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 获取未初始化切片的类型_Go_Reflection_Slice - Fatal编程技术网

Go 获取未初始化切片的类型

Go 获取未初始化切片的类型,go,reflection,slice,Go,Reflection,Slice,我想返回一种类型的接口{},而输入值可能是var m[]*MyModel 我已经设法找到了类型*MyModel,而MyModel不是因为我似乎无法找到指针 func getType( m interface{} ) reflect.Type { t := reflect.TypeOf( m ); v := reflect.ValueOf( m ); if t.Kind() == reflect.Ptr { if v.IsValid()

我想返回一种类型的
接口{}
,而输入值可能是
var m[]*MyModel

我已经设法找到了类型
*MyModel
,而
MyModel
不是因为我似乎无法找到指针

func getType( m interface{} ) reflect.Type {

    t := reflect.TypeOf( m );   
    v := reflect.ValueOf( m );

    if t.Kind() == reflect.Ptr {    

        if v.IsValid() && !v.IsNil() {          
            return getType( v.Elem().Interface() );         
        }

        panic( "We have a problem" );   

    }

    if t.Kind() == reflect.Slice {

        if v.Len() == 0 {           

            s := reflect.MakeSlice( t , 1 , 1 );            
            return getType( s.Interface() );    

        }

        return getType( v.Index( 0 ).Interface() );

    }

    return t;

}
有可能吗?

您可以使用获取类型的元素类型,该类型适用于
数组
Chan
映射
Ptr
切片

您可以运行一个循环并“导航”到该类型的元素类型,直到该类型既不是指针也不是片(如果需要,也不是数组、chan、map)

因此,简单的解决方案是:

func getElemType(a interface{}) reflect.Type {
    for t := reflect.TypeOf(a); ; {
        switch t.Kind() {
        case reflect.Ptr, reflect.Slice:
            t = t.Elem()
        default:
            return t
        }
    }
}
测试它:

type MyModel struct{}

fmt.Println(getElemType(MyModel{}))
fmt.Println(getElemType(&MyModel{}))
fmt.Println(getElemType([]MyModel{}))
fmt.Println(getElemType([]*MyModel{}))
fmt.Println(getElemType(&[]*MyModel{}))
fmt.Println(getElemType(&[]****MyModel{}))
fmt.Println(getElemType(&[][]**[]*[]***MyModel{}))
var p *[][]**[]*[]***MyModel
fmt.Println(p) // It's nil!
fmt.Println(getElemType(p))
输出(在上尝试):

注意#2:由于实现包含一个循环而不限制迭代计数,递归类型的值将使其进入一个无止境的循环,例如:

type RecType []RecType
getElemType(RecType{}) // Endless loop!

不加评论地否决?这是一个很好的反馈。你的解决方案很有魅力。我真的不明白,为什么需要
for
循环,但它可以工作,而不仅仅是
t:=reflect.TypeOf(a)
。你能解释一下吗?@MichaelSazonov如果你从类型
[]**MyModel
开始,
Elem()
将返回一个描述
**MyModel
的类型。再次调用
Elem()
将返回您的
*MyModel
,再次调用
Elem()
将得到
MyModel
。调用
Elem()
将剥离一个“类型层”。你需要一个循环来移除所有的“层”,直到你剩下的是“裸”类型。。。非常感谢你!
if a == nil {
    return nil
}
type RecType []RecType
getElemType(RecType{}) // Endless loop!