我想返回一种interface{}
类型,而输入值可能是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;
}
有可能吗?
答案 0 :(得分:2)
您可以使用Type.Elem()
获取类型的元素类型,该类型适用于Array
,Chan
,Map
,Ptr
和{ {1}}。
你可以运行一个循环并且"导航"到类型的元素类型,直到类型不是指针或切片(也不是数组,陈,地图,如果你需要)。
所以简单的解决方案是:
Slice
测试它:
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
}
}
}
输出(在Go Playground上尝试):
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))
正如你所看到的,无论深度如何"我们使用切片和指针(main.MyModel
main.MyModel
main.MyModel
main.MyModel
main.MyModel
main.MyModel
main.MyModel
<nil>
main.MyModel
),&[][]**[]*[]***MyModel{}
能够提取getElemType()
。
需要注意的一点是,在我的解决方案中,我使用了reflect.Type
而不是reflect.Value
。 Go是一种静态类型语言,所以即使我们传递了一个&#34; typed&#34;即使指针和切片元素没有填充&#34;,类型信息仍然存在。 main.MyModel
等nil
,我们仍然可以浏览&#34;类型链&#34;。
注意:如果使用无类型p
值调用上述getElemType()
恐慌,例如nil
,因为在这种情况下没有可用的类型信息。为了防止这种情况,您可以添加一个简单的检查:
getElemType(nil)
注意#2:由于实现包含一个不限制迭代计数的循环,递归类型的值会将其驱动为无限循环,例如:
if a == nil {
return nil
}