-2

I am super confused about this, I have:

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" {
            for _, z := range FlattenDeep((v.([]interface{}))...) {  // FAILS HERE
                list = append(list, z)
            }

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

}

the error is:

panic: interface conversion: interface {} is []func(http.HandlerFunc) http.HandlerFunc, not []interface {}

I don't understand, I thought a slice of anything could be converted to a slice of interface{}

I think I fixed the runtime error by doing this:

for _, v := range args {

    kind := getKind(v)
    if kind != "unknown" {

        a, ok := v.([]interface{})

        if ok == false {
           panic("o fuk")
        }

        for _, z := range FlattenDeep(a...) {
            list = append(list, z)
        }

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

still feels wrong tho, why Go? why

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
  • 2
    Check this post out: https://stackoverflow.com/questions/12753805/type-converting-slices-of-interfaces-in-go and this article: https://github.com/golang/go/wiki/InterfaceSlice – Henry Woody Dec 21 '18 at 02:30
  • 3
    A slice of anything cannot be converted to a []intereface{}. See the [FAQ for more information](https://golang.org/doc/faq#convert_slice_of_interface). Also, see answer to your [related question](https://stackoverflow.com/questions/53878197/flatten-arguments-list-where-arguments-might-be-slices-or-arrays) for a solution to the flatten problem. – Charlie Tumahai Dec 21 '18 at 02:48
  • 1
    Jesus, I thought at the very least slices/arrays could be generic, wtf am I supposed to do lol – Alexander Mills Dec 21 '18 at 02:54

1 Answers1

3

The types are not equivalent, as stated in the comments.

The operator you are attempting to use is called a "type assertion" not a "type conversion" for a reason. It does not manipulate the underlying data in any way. It merely asserts that the underlying data can be treated as if it were the asserted type (and in the single assignment form that you used, will panic if the type is incorrect).

I'll skip the explanation of why this doesn't work and go directly to answering the following question

Jesus, I thought at the very least slices/arrays could be generic, wtf am I supposed to do lol

Define the following function:

func toIfaceSlice(any interface{}) []interface{} {
    var out []interface{}
    rv := reflect.ValueOf(any)
    for i := 0; i < rv.Len(); i++ {
        out = append(out, rv.Index(i).Interface())
    }
    return out
}

Try on the Go Playground

And use it to convert v before recursing into FlattenDeep.

Note: for brevity, I left out any optimizations and error checking.

Joel Cornett
  • 24,192
  • 9
  • 66
  • 88
  • I assume `toIfaceSlice` would have to be called before every (recursive) call to FlattenDeep? – Alexander Mills Dec 21 '18 at 11:44
  • 1
    That’s correct. Obviously not optimal in terms of time complexity, but the point was to illustrate how one can convert elements of an arbitrary slice type into elements of type `interface{}`. – Joel Cornett Dec 21 '18 at 14:29
  • Crazy that I have to call a func to get type conversion or whatever you want to call it. Do you think there is any way to do this with the type system instead of "at runtime"? – Alexander Mills Dec 21 '18 at 23:19
  • 1
    @AlexanderMills it can’t possibly do it at compile time because the storage is different. As a thought experiment, think about casting an `int8` array to a `int16` array. This would not be possible without some sort of memory allocation and copying. Otherwise the indexes would be in the wrong place! `interface{}` is a specific variable type which is effectively a struct containing two fields: a pointer to a concrete type definition and a pointer to a data location. Does this answer your question or did I miss the point? – Joel Cornett Dec 31 '18 at 17:54