指针、数组和切片的结构值



我想有一种通用的方式,无论它是作为指针,切片还是数组提供,都将始终返回结构体值。

我的方法是:

func main() {
    p := Person{}
    if value(p).Kind() != reflect.Struct {
        fmt.Printf("Error 1")
    }
    if value(&p).Kind() != reflect.Struct {
        fmt.Printf("Error 2")
    }   
    if value([]Person{p}).Kind() != reflect.Struct {
        fmt.Printf("Error 3")
    }
    if value(&[]Person{p}).Kind() != reflect.Struct {
        fmt.Printf("Error 4")
    }
}
func value(m interface{}) reflect.Value {
    v := reflect.ValueOf(m)
    switch v.Kind() {
    case reflect.Ptr:
        v = v.Elem()
        fallthrough
    case reflect.Slice, reflect.Array:
        v = v.Elem()
    }
    return v
}

去操场

正如您所看到的,问题在于将结构体从slicearray中取出。

我如何需要扩展上述函数,以获得结构体值与在数组或切片?

更新:我要做的是把[]People变成People

如果你只是想要类型,即使切片是nil,你可以使用这样的东西:

func value(m interface{}) reflect.Type {
    t := reflect.Indirect(reflect.ValueOf(m)).Type()
    if t.Kind() == reflect.Slice || t.Kind() == reflect.Array {
        t = t.Elem()
        if t.Kind() == reflect.Ptr {
            t = t.Elem()
        }
        return t
    }
    return t
}

关于Type.Elem(), from http://golang.org/pkg/reflect/#Type:

//Elem返回类型的元素类型。

//如果类型的类型不是Array、Chan、Map、Ptr或Slice,则会产生panic

//edit更新了函数,使其可以在指针切片上工作

我认为您所说的"从切片或数组中取出"的意思是您想要第一个元素(即索引为0的元素)?如果这是您想要的,那么您应该使用reflect.Value.Index()方法。例如:

func value(m interface{}) reflect.Value {
    v := reflect.ValueOf(m)
    switch v.Kind() {
    case reflect.Ptr:
        v = v.Elem()
        if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {
            v = v.Index(0)
        }
    case reflect.Slice, reflect.Array:
        v = v.Index(0)
    default:
        break LOOP
    }
    return v
}

去操场

注意,我还稍微修改了流逻辑。你从指针的情况掉到了切片/数组的情况。您可能希望再次测试case条件(因此它实际上会说,"如果这是一个指针,现在检查它指向的东西是切片还是数组"),但这不是fallthrough的工作方式。现在它显式地检查大小写

相关内容

  • 没有找到相关文章

最新更新