Type converting slices of interfaces

后端 未结 6 1605
孤街浪徒
孤街浪徒 2020-11-22 04:04

I\'m curious why Go does\'t implicitly convert []T to []interface{} when it will implicitly convert T to interface{}. Is

相关标签:
6条回答
  • 2020-11-22 04:39

    Try interface{} instead. To cast back as slice, try

    func foo(bar interface{}) {
        s := bar.([]string)
        // ...
    }
    
    0 讨论(0)
  • 2020-11-22 04:39

    Convert interface{} into any type.

    Syntax:

    result := interface.(datatype)
    

    Example:

    var employee interface{} = []string{"Jhon", "Arya"}
    result := employee.([]string)   //result type is []string.
    
    0 讨论(0)
  • 2020-11-22 04:40

    The thing you are missing is that T and interface{} which holds a value of T have different representations in memory so can't be trivially converted.

    A variable of type T is just its value in memory. There is no associated type information (in Go every variable has a single type known at compile time not at run time). It is represented in memory like this:

    • value

    An interface{} holding a variable of type T is represented in memory like this

    • pointer to type T
    • value

    So coming back to your original question: why go does't implicitly convert []T to []interface{}?

    Converting []T to []interface{} would involve creating a new slice of interface {} values which is a non-trivial operation since the in-memory layout is completely different.

    0 讨论(0)
  • 2020-11-22 04:52

    Here is the official explanation: https://github.com/golang/go/wiki/InterfaceSlice

    var dataSlice []int = foo()
    var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
    for i, d := range dataSlice {
        interfaceSlice[i] = d
    }
    
    0 讨论(0)
  • 2020-11-22 04:54

    In Go, there is a general rule that syntax should not hide complex/costly operations. Converting a string to an interface{} is done in O(1) time. Converting a []string to an interface{} is also done in O(1) time since a slice is still one value. However, converting a []string to an []interface{} is O(n) time because each element of the slice must be converted to an interface{}.

    The one exception to this rule is converting strings. When converting a string to and from a []byte or a []rune, Go does O(n) work even though conversions are "syntax".

    There is no standard library function that will do this conversion for you. You could make one with reflect, but it would be slower than the three line option.

    Example with reflection:

    func InterfaceSlice(slice interface{}) []interface{} {
        s := reflect.ValueOf(slice)
        if s.Kind() != reflect.Slice {
            panic("InterfaceSlice() given a non-slice type")
        }
    
        // Keep the distinction between nil and empty slice input
        if s.IsNil() {
            return nil
        }
    
        ret := make([]interface{}, s.Len())
    
        for i:=0; i<s.Len(); i++ {
            ret[i] = s.Index(i).Interface()
        }
    
        return ret
    }
    

    Your best option though is just to use the lines of code you gave in your question:

    b := make([]interface{}, len(a))
    for i := range a {
        b[i] = a[i]
    }
    
    0 讨论(0)
  • In case you need more shorting your code, you can creating new type for helper

    type Strings []string
    
    func (ss Strings) ToInterfaceSlice() []interface{} {
        iface := make([]interface{}, len(ss))
        for i := range ss {
            iface[i] = ss[i]
        }
        return iface
    }
    

    then

    a := []strings{"a", "b", "c", "d"}
    sliceIFace := Strings(a).ToInterfaceSlice()
    
    0 讨论(0)
提交回复
热议问题