Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot convert []string to []interface {}

I'm writing some code, and I need it to catch the arguments and pass them through fmt.Println
(I want its default behaviour, to write arguments separated by spaces and followed by a newline). However it takes []interface {} but flag.Args() returns a []string.
Here's the code example:

package main  import (     "fmt"     "flag" )  func main() {     flag.Parse()     fmt.Println(flag.Args()...) } 

This returns the following error:

./example.go:10: cannot use args (type []string) as type []interface {} in function argument 

Is this a bug? Shouldn't fmt.Println take any array? By the way, I've also tried to do this:

var args = []interface{}(flag.Args()) 

but I get the following error:

cannot convert flag.Args() (type []string) to type []interface {} 

Is there a "Go" way to workaround this?

like image 306
cruizh Avatar asked Oct 20 '12 16:10

cruizh


2 Answers

This is not a bug. fmt.Println() requires a []interface{} type. That means, it must be a slice of interface{} values and not "any slice". In order to convert the slice, you will need to loop over and copy each element.

old := flag.Args() new := make([]interface{}, len(old)) for i, v := range old {     new[i] = v } fmt.Println(new...) 

The reason you can't use any slice is that conversion between a []string and a []interface{} requires the memory layout to be changed and happens in O(n) time. Converting a type to an interface{} requires O(1) time. If they made this for loop unnecessary, the compiler would still need to insert it.

like image 148
Stephen Weinberg Avatar answered Sep 30 '22 16:09

Stephen Weinberg


In this case, a type conversion is unnecessary. Simply pass the flag.Args() value to fmt.Println.


Question:

Cannot convert []string to []interface {}

I'm writing some code, and I need it to catch the arguments and pass them through fmt.Println (I want its default behaviour, to write arguments separated by spaces and followed by a newline).

Here's the code example:

package main  import (     "fmt"     "flag" )  func main() {     flag.Parse()     fmt.Println(flag.Args()...) } 

Package flag

import "flag"

func Args

func Args() []string

Args returns the non-flag command-line arguments.


Package fmt

import "fmt"

func Println

func Println(a ...interface{}) (n int, err error)

Println formats using the default formats for its operands and writes to standard output. Spaces are always added between operands and a newline is appended. It returns the number of bytes written and any write error encountered.


In this case, a type conversion is unnecessary. Simply pass the flag.Args() value to fmt.Println, which uses reflection to interpret the value as type []string. Package reflect implements run-time reflection, allowing a program to manipulate objects with arbitrary types. For example,

args.go:

package main  import (     "flag"     "fmt" )  func main() {     flag.Parse()     fmt.Println(flag.Args()) } 

Output:

$ go build args.go $ ./args arg0 arg1 [arg0 arg1] $  
like image 37
peterSO Avatar answered Sep 30 '22 15:09

peterSO