50

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.

0

3 Answers 3

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) } 
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for your answer, and i have another question is that can []interface{slice...} be work? Just like []interface{"aaa", "bbb"}
@cosiner do you mean as used in a function API? I see that more as passing parameters to variadic functions: golang.org/ref/spec#Passing_arguments_to_..._parameters
@cosiner for slices, you can try the append() function instead: golang.org/ref/spec#Appending_and_copying_slices
thanks, may be there is no common method to convert []type to []interface{}, must define a series of functions for each type use append.
@TomL Thank you. I have included your example in the answer for more visibility.
|
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)) 

1 Comment

What woule be the equivalent for map?
2

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 } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.