2017-08-15 66 views
0

我需要检查interface {}是否是一个数组,如果是,则创建相应的片。不幸的是,我不知道数组的长度。是否可以在Golang类型声明中使用反射数组类型?

例如:

import (
    "reflect" 
) 
func AnythingToSlice(a interface{}) []interface{} { 
    rt := reflect.TypeOf(a) 
    switch rt.Kind() { 
    case reflect.Slice: 
    slice, ok := a.([]interface{}) 
    if ok { 
     return slice 
    } 
    // it works 

    case reflect.Array: 
    // return a[:] 
    // it doesn't work: cannot slice a (type interface {}) 
    // 
    array, ok := a.([reflect.ValueOf(a).Len()]interface{}) 
    // :-(((non-constant array bound reflect.ValueOf(a).Len() 
    if ok { 
     return array[:] 
    } 

    } 
    return []interface{}(a) 
} 
+2

机会是你永远不会看到界面的'数组{}',所以你需要的元素反正复制。如果它不是可寻址的,你也不能切片数组值,所以它需要传递一个指向'interface {}'的数组的指针,这是你不太可能遇到的。由于Go类型是不变的,并且很可能您需要复制这些值,所以您试图解决的实际问题是什么? – JimB

+0

这只是从脚本编程中获得的私人风格。当我解析JSON时,我想隐式地将一些值转换为数组。例如: { “a”:[1,2,3] //没关系 “b”:1 //必须转换为[1] “c”:{} //它必须是转换为[{}] } 所以我需要通用函数来将任何东西转换为切片。我明白Golang不是JS,Python或Perl,但它是我第一次使用Golang样本。 –

回答

2

一个明确的类型是在一个类型的断言必需的。该类型不能通过反射来构建。

除非参数是[] interface {},否则必须复制片或数组以产生[] interface {}。

试试这个:

func AnythingToSlice(a interface{}) []interface{} { 
    v := reflect.ValueOf(a) 
    switch v.Kind() { 
    case reflect.Slice, reflect.Array: 
     result := make([]interface{}, v.Len()) 
     for i := 0; i < v.Len(); i++ { 
      result[i] = v.Index(i).Interface() 
     } 
     return result 
    default: 
     panic("not supported") 
    } 
} 

https://play.golang.org/p/3bXxnHOK8_

+0

因此有一个数组我不能直接得到它的切片,并且必须创建一个副本。这很可惜,但我明白这个麻烦。 –

相关问题