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?
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.
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]
$
If it's only a slice of strings you want to print, you can avoid conversion and get the exact same output by joining:
package main
import (
"fmt"
"flag"
"strings"
)
func main() {
flag.Parse()
s := strings.Join(flag.Args(), " ")
fmt.Println(s)
}