49

I just want to write some code like this:

func (w Writer) WriteVString(strs []string) (int, error) {
    return writeV(func(index int, str interface{}) (int, error) {
        return w.WriteString(str.(string))
    }, strs) // it doesn't work
}

func (w Writer) WriteV(bs [][]byte) (int, error) {
    return writeV(func(index int, b interface{}) (int, error) {
        return w.Write(b.([]byte))
    }, []interface{}{bs...}) // it also can't be compiled
}
type writeFunc func(int, interface{}) (int, error)

func writeV(fn writeFunc, slice []interface{}) (n int, err error) {
    var m int
    for index, s := range slice {
        if m, err = fn(index, s); err != nil {
            break
        }
        n += m
    )
    return
}

I thought interface{} can represent any type, so []interface can also represent any []type before, now I know I'm wrong, []type is a whole type, can't be considered as []interface{}.

So, can anyone help me how to make this code work, or any other solution?

PS: I know that []byte or string can be converted to one another, but it's not actually my intention, may be there is another type rather than []byte and string.

Draken
  • 3,134
  • 13
  • 34
  • 54
zhuah
  • 571
  • 1
  • 4
  • 13

3 Answers3

59

now I know I'm wrong, []type is a whole type, can't be considered as []interface{}.

Yes, and that is because interface{} is its own type (and not an "alias" for any other type).
As I mention in "what is the meaning of interface{} in golang?" (if v is a interface{} variable):

Beginner gophers are led to believe that “v is of any type”, but that is wrong.
v is not of any type; it is of interface{} type.

The FAQ mentions

they do not have the same representation in memory.

It is necessary to copy the elements individually to the destination slice.
This example converts a slice of int to a slice of interface{}:

t := []int{1, 2, 3, 4}
s := make([]interface{}, len(t))
for i, v := range t {
    s[i] = v
}

Tom L propose this example (in the comments):

package main

import "fmt"

func main() {

    x := []string{"a", "b", "c", "d"}
    fmt.Printf("%T: %v\n", x, x)

    //converting a []string to a []interface{}
    y := make([]interface{}, len(x))
    for i, v := range x {
        y[i] = v
    }
    fmt.Printf("%T: %v\n", y, y)

    //converting a []interface{} to a []string
    z := make([]string, len(y))
    for i, v := range y {
        z[i] = fmt.Sprint(v)
    }
    fmt.Printf("%T: %v\n", z, z)

}
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thanks for your answer, and i have another question is that can `[]interface{slice...}` be work? Just like `[]interface{"aaa", "bbb"}` – zhuah Dec 29 '14 at 12:52
  • @cosiner do you mean as used in a function API? I see that more as passing parameters to variadic functions: https://golang.org/ref/spec#Passing_arguments_to_..._parameters – VonC Dec 29 '14 at 12:58
  • @cosiner for slices, you can try the `append()` function instead: https://golang.org/ref/spec#Appending_and_copying_slices – VonC Dec 29 '14 at 12:59
  • thanks, may be there is no common method to convert []type to []interface{}, must define a series of functions for each type use `append`. – zhuah Dec 29 '14 at 13:11
  • Yes, and you can use the new generate feature from go1.4 to do that. – VonC Dec 29 '14 at 13:16
  • Example on the [Go Playground](https://play.golang.org/p/9jpvgCjIr3r) that converts a `[]string` to an `[]interface{}` and then back to a `[]string`. –  Mar 05 '20 at 04:27
  • 1
    @TomL Thank you. I have included your example in the answer for more visibility. – VonC Mar 05 '20 at 06:57
  • @VonC Thank you. –  Mar 05 '20 at 06:59
11
  1. Create a utility function, like this
func ToGenericArray(arr ...interface{}) []interface{} {
    return arr
}
  1. And use it:
func yourfunc(arr []interface{})  {
....
}

yourfunc(ToGenericArray([...]string{"a", "b", "c"}))

  1. IMPORTANT NOTICE: the following will not work
func yourfunc(arr []interface{})  {
....
}

arr:=[...]string{"a", "b", "c"}

yourfunc(ToGenericArray(arr))

sɐunıɔןɐqɐp
  • 3,332
  • 15
  • 36
  • 40
jashawnpeng
  • 111
  • 1
  • 2
0

With generics, useful with sql package

func toAnyList[T any](input []T) []any{
    list := make([]any, len(input))
    for i, v := range input {
        list[i] = v
    }
    return list
}
rde
  • 1