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)
}
In Go, a function can only accept arguments of the types specified in the parameter list in the function definition. The variadic parameter language feature complicates that a bit, but it follows well-defined rules.
The function signature for fmt.Println is:
func Println(a ...interface{}) (n int, err error)
Per the language specifiction,
The final incoming parameter in a function signature may have a type prefixed with .... A function with such a parameter is called variadic and may be invoked with zero or more arguments for that parameter.
This means you can pass Println a list of arguments of interface{} type. Since all types implement the empty interface, you can pass a list of arguments of any type, which is how you're able to call Println(1, "one", true), for example, without error. See the "Passing arguments to ... parameters" section of the language specification:
the value passed is a new slice of type []T with a new underlying array whose successive elements are the actual arguments, which all must be assignable to T.
The part that's giving you trouble is right after that in the specification:
If the final argument is assignable to a slice type []T, it may be passed unchanged as the value for a ...T parameter if the argument is followed by .... In this case no new slice is created.
flag.Args() is type []string. Since T in Println is interface{}, []T is []interface{}. So the question comes down to whether a string slice value is assignable to a variable of interface slice type. You can easily test that in your go code by attempting an assignment, for example:
s := []string{}
var i []interface{}
i = s
If you attempt such an assignment, the compiler will output this error message:
cannot use s (type []string) as type []interface {} in assignment
And that's why you can't use the ellipsis after a string slice as an argument to fmt.Println. It's not a bug, it's working as intended.
There are still lots of ways you can print flag.Args() with Println, such as
fmt.Println(flag.Args())
(which will output as [elem0 elem1 ...], per fmt package documentation)
or
fmt.Println(strings.Join(flag.Args(), ` `)
(which will output the string slice elements, each separated by a single space) using the Join function in the strings package with a string separator, for example.
Another option is to just iterate the slice:
package main
import "flag"
func main() {
flag.Parse()
for _, each := range flag.Args() {
println(each)
}
}
I think it's possible using reflection, but I don't know if it's a good solution
package main
import (
"fmt"
"reflect"
"strings"
)
type User struct {
Name string
Age byte
}
func main() {
flag.Parse()
fmt.Println(String(flag.Args()))
fmt.Println(String([]string{"hello", "world"}))
fmt.Println(String([]int{1, 2, 3, 4, 5, 6}))
u1, u2 := User{Name: "John", Age: 30},
User{Name: "Not John", Age: 20}
fmt.Println(String([]User{u1, u2}))
}
func String(v interface{}) string {
val := reflect.ValueOf(v)
if val.Kind() == reflect.Array || val.Kind() == reflect.Slice {
l := val.Len()
if l == 0 {
return ""
}
if l == 1 {
return fmt.Sprint(val.Index(0))
}
sb := strings.Builder{}
sb.Grow(l * 4)
sb.WriteString(fmt.Sprint(val.Index(0)))
for i := 1; i < l; i++ {
sb.WriteString(",")
sb.WriteString(fmt.Sprint(val.Index(i)))
}
return sb.String()
}
return fmt.Sprintln(v)
}
Output:
$ go run .\main.go arg1 arg2
arg1,arg2
hello,world
1,2,3,4,5,6
{John 30},{Not John 20}
fmt.Println takes variadic parameter
func Println(a ...interface{}) (n int, err error)
Its possible to print flag.Args() without converting into []interface{}
func main() {
flag.Parse()
fmt.Println(flag.Args())
}
Related
If I give a function parameter a default value that is a not a constant (e.g. the result of a function call) is that value just evaluated once (and if so, when?) or is it evaluated every time the function is called?
From The Swift Programming Language, under Language Reference > Declarations > Special Kinds of Parameters:
A parameter with an equals sign (=) and an expression after its type is understood to have a default value of the given expression. The given expression is evaluated when the function is called. If the parameter is omitted when calling the function, the default value is used instead.
You can demonstrate this for yourself by putting the following in a playground:
import Foundation
func foo(i: UInt32 = arc4random()) {
print(i)
}
foo()
foo()
foo()
foo()
foo()
which will print five different random numbers (unless the random number generator generates the same number five times by some astronomically improbable coincidence).
It's not explicit in the docs quoted above, so it's worth noting that when you do specify the argument when calling the function the default expression is not evaluated. You can demonstrate that in a playground too:
func getSomeInt() -> Int {
print("getSomeInt() was called")
return 42
}
func bar(_ i: Int = getSomeInt()) {
print(i)
}
bar(1)
and when that runs you'll see that "getSomeInt() was called" is not printed.
Here's a Swift function that takes in two ints and a three-arg function, and calls the passed-in function.
func p(x:Int, _ y:Int, _ f: (Int, Int, Int) -> ()) {
f(x, y, 0)
}
I can call this just fine using both trailing closure syntax and shorthand argument names, no problem:
> p(1, 2) {print($0 + $1 + $2)}
3
That worked as expected. But in the Foundation library, there is a string method called enumerateSubstringsInRange defined as follows:
func enumerateSubstringsInRange(
_ range: Range<Index>,
options opts: NSStringEnumerationOptions,
_ body: (substring: String?,
substringRange: Range<Index>,
enclosingRange: Range<Index>,
inout Bool) -> ())
Okay, that's easy enough: the function takes three arguments, the last of which is four-argument function. Just like my first example! Or so I thought....
I can use this function with the trailing closure syntax, but I cannot use shorthand argument names! I have no idea why. This is what I tried:
let s = "a b c"
"a b c".enumerateSubstringsInRange(s.characters.indices, options: .ByWords) {(w,_,_,_) in print(w!)}
a
b
c
All good; I just wanted to print out the matched words, one at a time. That worked when I specified by closure as ``{(w,,,_) in print(w!)}`. HOWEVER, when I try to write the closure with shorthand argument syntax, disaster:
> "a b c".enumerateSubstringsInRange(s.characters.indices, options: .ByWords) {print($0!)}
repl.swift:9:86: error: cannot force unwrap value of non-optional type '(substring: String?, substringRange: Range<Index>, enclosingRange: Range<Index>, inout Bool)' (aka '(substring: Optional<String>, substringRange: Range<String.CharacterView.Index>, enclosingRange: Range<String.CharacterView.Index>, inout Bool)')
So what did I do wrong?! The error message seems to say that closure argument $0 is the whole tuple of args. And indeed, when I tried that, that sure seems to be the case!
>"a b c".enumerateSubstringsInRange(s.characters.indices, options: .ByWords) {print($0.0!)}
a
b
c
So I'm terribly confused. Why in the first case (my function p, are the arguments understood to be $0, $1, etc., but in the second case, all the arguments are rolled up into a tuple? Or are they? FWIW, I found the signature of enumerateSubstringsInRange here.
It depends on the number of parameters.
For example,
func test( closure: (Int,Int,Int) -> Void ){
// do something
}
To make test works as you expect, you must specify $2 ( 3rd argument ). The compiler will infer to the values inside tuple, otherwise it will infer to the tuple itself.
If you don't specify $number that match the number of parameters. For example, only specify $1, will make compile error.
// work as expected ( infer to int )
test{
print($2)
}
test{
print($1+$2)
}
test{
print($0+$1+$2)
}
// not work ( infer to tuple )
test{
print($0)
}
// not work ( cannot infer and compile error )
test{
print($1)
}
There is a question relate to this question. Why is the shorthand argument name $0 returning a tuple of all parameters?
In Swift, how is tuple related to function argument?
In the following two examples the function returns the same type even though one takes a tuple while the other takes two arguments. From the caller standpoint (without peeking at the code), there is no difference whether the function takes a tuple or regular arguments.
Is function argument related to tuple in some ways?
e.g.
func testFunctionUsingTuple()->(Int, String)->Void {
func t(x:(Int, String)) {
print("\(x.0) \(x.1)")
}
return t
}
func testFuncUsingArgs()->(Int, String)->Void {
func t(x:Int, y:String) {
print("\(x) \(y)")
}
return t
}
do {
var t = testFunctionUsingTuple()
t(1, "test")
}
do {
var t = testFuncUsingArgs()
t(1, "test")
}
There is also inconsistencies in behavior when declaring tuple in function argument in a regular function (rather than a returned function):
func funcUsingTuple(x:(Int, String)) {
print("\(x.0) \(x.1)")
}
func funcUsingArgs(x:Int, _ y:String) {
print("\(x) \(y)")
}
// No longer works, need to call funcUsingTuple((1, "test")) instead
funcUsingTuple(1, "test")
funcUsingArgs(1, "test3")
UPDATED:
Chris Lattner's clarification on tuple:
"x.0” where x is a scalar value produces that scalar value, due to odd
behavior involving excessive implicit conversions between scalars and
tuples. This is a bug to be fixed.
In "let x = (y)”, x and y have the same type, because (x) is the
syntax for a parenthesis (i.e., grouping) operator, not a tuple
formation operator. There is no such thing as a single-element
unlabeled tuple value.
In "(foo: 42)” - which is most commonly seen in argument lists -
you’re producing a single element tuple with a label for the element.
The compiler is currently trying hard to eliminate them and demote
them to scalars, but does so inconsistently (which is also a bug).
That said, single-element labeled tuples are a thing.
Every function takes exactly one tuple containing the function's arguments. This includes functions with no arguments which take () - the empty tuple - as its one argument.
Here is how the Swift compiler translates various paren forms into internal representations:
() -> Void
(x) -> x
(x, ...) -> [Tuple x ...]
and, if there was a tuple? function, it would return true on: Void, X, [Tuple x ...].
And here is your proof:
let t0 : () = ()
t0.0 // error
let t1 : (Int) = (100)
t1.0 -> 100
t1.1 // error
let t2 : (Int, Int) = (100, 200)
t2.0 -> 100
t2.1 -> 200
t2.2 // error
[Boldly stated w/o a Swift interpreter accessible at the moment.]
From AirSpeedVelocity
But wait, you ask, what if I pass something other than a tuple in?
Well, I answer (in a deeply philosophical tone), what really is a
variable if not a tuple of one element? Every variable in Swift is a
1-tuple. In fact, every non-tuple variable has a .0 property that is
the value of that variable.4 Open up a playground and try it. So if
you pass in a non-tuple variable into TupleCollectionView, it’s legit
for it to act like a collection of one. If you’re unconvinced, read
that justification again in the voice of someone who sounds really
confident.
Remember the 'philosophical tone' as we've reached the 'I say potato; your say potato' phase.
A function in Swift takes a tuple as parameter, which can contain zero or more values. A parameterless function takes a tuple with no value, a function with one parameter takes a tuple with 1 value, etc.
You can invoke a function by passing parameters individually, or by grouping them into an immutable tuple. For example, all these invocations are equivalent:
do {
let t1 = testFunctionUsingTuple()
let t2 = testFuncUsingArgs()
let params = (1, "tuple test")
t1(params)
t1(2, "test")
t2(params)
t2(3, "test")
}
Reference Go equivalent of a void pointer in C
this is a demo.
package main
import (
"fmt"
)
func map_exist(map_val map[string]interface{}, key string) bool {
_, ok := map_val[key]
return ok
}
func main() {
var one map[string][]string
one["A"] = []string{"a", "b", "c"}
fmt.Println(map_exist(one, "A"))
var two map[string]string
two["B"] = "a"
fmt.Println(map_exist(two, "B"))
}
run result:
./main.go:15: cannot use one (type map[string][]string) as type map[string]interface {} in argument to map_exist
./main.go:19: cannot use two (type map[string]string) as type map[string]interface {} in argument to map_exist
I can not find a data structure to be able to contain any type .
It's true that interface{} is kind of like C's void *, but you can't implicitly convert a map[string]string into a map[string]interface{}. The key is to define your map objects at their declaration as map[string]interface{} objects. Unfortunately, you cannot assign new values to such a map, since Go can't know how much memory to allocate for each instance.
func main() {
one := map[string]interface{} {
"A": []string{"a", "b", "c"},
}
fmt.Println(map_exist(one, "A"))
two := map[string]interface{} {
"B": "a",
}
fmt.Println(map_exist(two, "B"))
}
This works, but it probably isn't useful enough for your intended use case.
Another approach is to define a generic map interface and make sure that the functions you intend to use are defined for the types you want to support. Basically, your goal is to build a library that's useful enough that you can reasonably offload the work of implementing your interface to the library's users. It would be nice if you could declare a default function or maybe just a macro to prevent the copy-paste, but I'm not aware of such a mechanism.
Here's an example using an interface:
type GenericMap interface{
ValueForKey(string) (interface{}, bool)
}
type SliceMap map[string][]string
type StringMap map[string]string
type VoidMap map[string]interface{}
func map_exist(map_val GenericMap, key string) bool {
_, ok := map_val.ValueForKey(key)
return ok
}
func (map_val SliceMap) ValueForKey(key string) (interface{}, bool) {
val, ok := map_val[key]
return val, ok
}
func (map_val StringMap) ValueForKey(key string) (interface{}, bool) {
val, ok := map_val[key]
return val, ok
}
func (map_val VoidMap) ValueForKey(key string) (interface{}, bool) {
val, ok := map_val[key]
return val, ok
}
func main() {
one := SliceMap {
"A": []string{"a", "b", "c"},
}
fmt.Println(map_exist(GenericMap(one), "A"))
two := StringMap {
"B": "a",
}
fmt.Println(map_exist(GenericMap(two), "B"))
}
In the end, Go programmers tend to prefer a simple, straight-forward solution over all this misdirection, so your best bet is to just use the construct proposed by #Logiraptor:
if _, ok := m[key]; ok {
// You're ok!
}
Go does not support parametric polymorphism. What you're trying to do is only possible with reflection which will be much longer and more error prone than just using the _, ok := m[key] form. Usually you would write it like so:
if _, ok := m[key]; ok {
// do something conditionally.
}
I am playing with type assertion using the following dummy code, and I got the error:
cannot type switch on non-interface value
Does anyone know what does that mean?
package main
import "fmt"
import "strconv"
type Stringer interface {
String() string
}
type Number struct {
v int
}
func (number *Number) String() string {
return strconv.Itoa(number.v)
}
func main() {
n := &Number{1}
switch v := n.(type) {
case Stringer:
fmt.Println("Stringer:", v)
default:
fmt.Println("Unknown")
}
}
http://play.golang.org/p/Ti4FG0m1mc
I figured out the answer, which is to cast n to interface{} before the type assertion:
switch v := interface{}(n).(type)
Type switches require an interface to introspect. If you are passing a value of known type to it it bombs out. If you make a function that accepts an interface as a parameter, it will work:
func typeSwitch(tst interface{}) {
switch v := tst.(type) {
case Stringer:
fmt.Println("Stringer:", v)
default:
fmt.Println("Unknown")
}
}
See the full code here http://play.golang.org/p/QNyf0eG71_ and the golang documentation on interfaces http://golang.org/doc/effective_go.html#interfaces.
There are two kinds of type conversions
conversion between basic data types. For this we can use the direct casting
i := 48
str := string(i)
But type conversion using value.(type) is for conversion among the class hierarchy, (e.g. where we want to get the specific implementation from the interface). Else, we get the above error.
There are no typecasts in Go. You are doing a type conversion.