go - 获取未初始化 slice 的类型

标签 go reflection slice

我想返回一个接口(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;

}

这可能吗?

最佳答案

您可以使用 Type.Elem()获取类型的元素类型,适用于 ArrayChanMapPtrSlice

您可以运行一个循环并“导航”到该类型的元素类型,直到该类型既不是指针也不是 slice (如果需要,也不是数组、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))

输出(在 Go Playground 上尝试):

main.MyModel
main.MyModel
main.MyModel
main.MyModel
main.MyModel
main.MyModel
main.MyModel
<nil>
main.MyModel

如您所见,无论我们使用 slice 和指针有多“深入”(&[][]**[]*[]***MyModel{}),getElemType() 能够提取main.MyModel

需要注意的是,在我的解决方案中,我使用了 reflect.Type而不是 reflect.Value . Go 是一种静态类型语言,因此即使指针和 slice 元素未被“填充”,类型信息也存在,即使我们传递“类型化”nil 例如 p,我们仍然能够在“类型链”中导航。

注意:如果使用未类型化的 nil 值调用上述 getElemType(),例如getElemType(nil),因为在这种情况下没有可用的类型信息。为了捍卫这一点,您可以添加一个简单的检查:

if a == nil {
    return nil
}

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

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

关于go - 获取未初始化 slice 的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39467591/

相关文章:

gorm 多对一返回空

c# - GetType(string) 在 AppDomain.CurrentDomain.Load 之后返回 null

c# - 读取方法属性的值

c# - 从对象中获取自定义属性

sql - 预期 slice 但得到界面

python - 如何通过列索引列表对 numpy 数组进行切片

java - 将 Kafka 的 murmur2 实现移植到 Go

go - 如何检查操作系统上是否安装了程序/软件包?

validation - 如何根据 http 方法类型设置不同的验证约束?

go - Go 中的 slice 如何不被取消引用?