展平参数列表,其中参数可能是切片或数组

flatten arguments list, where arguments might be slices or arrays

如果我有这样的功能:

func AcceptsAnything(v ...interface{}){
  args =: FlattenDeep(v);  // flatten any arrays or slices
}

我正在尝试实施 FlattenDeep:

func getKind(v interface{}) string {

    rt := reflect.TypeOf(v)
    switch rt.Kind() {
    case reflect.Slice:
        return "slice"
    case reflect.Array:
        return "array"
    default:
        return "unknown"
    }

}

func FlattenDeep(args ...interface{}) []interface{} {
    list := []interface{}{}

   for _, v := range args {

     kind := getKind(v);

     if kind != "unknown" {
        list = append(list, FlattenDeep(v)...)  // does not compile
     } else{
        list = append(list, v);
       }
    }
   return list;
}

但我不知道如何一次将多个项目附加到列表中。我应该只循环 FlattenDeep 的结果还是有办法传播结果并将它们附加到列表中?

这可能有效:

func FlattenDeep(args ...interface{}) []interface{} {
    list := []interface{}{}

    for _, v := range args {

        kind := getKind(v);
        if kind != "unknown" {
            for _, z := range FlattenDeep((v.([]interface{})...) {
                list = append(list, z)
            }

        } else {
            list = append(list, v);
        }
    }
    return list;
}

但如果可能的话,我正在寻找一些不那么冗长的东西

以下是将任意切片和数组展平为 []接口{}的方法:

func flattenDeep(args []interface{}, v reflect.Value) []interface{} {

    if v.Kind() == reflect.Interface {
        v = v.Elem()
    }

    if v.Kind() == reflect.Array || v.Kind() == reflect.Slice {
        for i := 0; i < v.Len(); i++ {
            args = flattenDeep(args, v.Index(i))
        }
    } else {
        args = append(args, v.Interface())
    }

    return args
}

func AcceptsAnything(v ...interface{}) {
    args := flattenDeep(nil, reflect.ValueOf(v))
    fmt.Println(args)
}

Run it on the Playground

如果函数必须处理具有任意元素类型的切片和数组类型,则应用程序必须使用反射 API 遍历切片或数组以将值放入 []接口{}。

如果你只需要扁平化[]interface{},那么反射API是不需要的:

func flattenDeep(args []interface{}, v interface{}) []interface{} {
    if s, ok := v.([]interface{}); ok {
        for _, v := range s {
            args = flattenDeep(args, v)
        }
    } else {
        args = append(args, v)
    }
    return args
}

func AcceptsAnything(v ...interface{}) {
    args := flattenDeep(nil, v)
    fmt.Println(args)
}

Run it on the Playground.