How can I pass dictionary as list of arguments for function like in Python 3 in Go?
Python 3:
def bar(a,b,c):
print(a,b,c)
args={c: 1, b: 2, a: 3}
bar(**args)
Go blank:
func bar( a, b, c int) {
fmt.Printf("%d, %d, %d", a, b, c)
}
func main(){
args := make(map[string]int)
args["a"] = 3
args["b"] = 2
args["c"] = 1
// what next ?
}
I don't believe this is possible. You'd need to use a struct to do anything even remotely close to this (and it is a remote likeness)
type Args struct {
A, B, C int
}
func bar(args *Args) {
fmt.Printf("%d, %d, %d", args.A, args.B, args.C)
}
func main() {
args := new(Args)
args.A = 3
args.B = 2
args.C = 1
bar(args)
}
For completeness sake you can either use what dskinner said, or if you want a "dictionary" (called map in Go) you could use one easily, for example
:
package main
import "log"
type ArgsMap map[string]interface{}
func bar(am ArgsMap) {
if v, ok := am["foo"].(string); ok {
log.Println("bar", v)
} else {
log.Println("bar no foo")
}
}
// Or
type Args struct {
foo string
boo int
a, b, c float32
}
func bar2(a Args) {
if a.foo != "" {
log.Println("bar2", a.foo)
} else {
log.Println("bar2 no foo")
}
}
func main() {
bar(ArgsMap{"foo": "map", "blah": 10})
bar(ArgsMap{})
bar2(Args{foo: "struct"})
bar2(Args{})
}
There is no direct equivalent to Python's *args/**kwargs
syntax. You need to use one of the solutions outlined in the other answers.
In case you just need to pass an unknown number of arguments you can make your function variadic.
package main
import (
"fmt"
)
func bar(numbers ...int) {
fmt.Printf("%d
", numbers)
}
func main() {
bar(3, 2, 1) // prints [3 2 1]
bar(5, 4, 3, 2, 1) // prints [5 4 3 2 1]
}
In addition to the other answers, which I see no need to repeat, be aware that Go will auto-unpack function calls with multiple return arguments provided:
(That is, the types of the function's argument list is identical to the other function's return list).
func Args() (a int, b int, c int) {
return 1,2,3
}
func Bar(a,b,c int) {
fmt.Println(a,b,c)
}
func main() {
Bar(Args())
}
Will print 1,2,3
. Obviously this example is a tad silly, but I find this covers most cases of tuple and dict unpacking as arguments in Python, which tend to be a quick and dirty way of passing one function's return values as another function's arguments.
This is not thoroughly tested for a wide range of values, but it works for a few simple cases. Feel free to expand it further for your own needs. It's also not guaranteed to be anything like the best way to do this, and error checking is left as an exercise for the reader.
func parseArguments(args ...interface{}) map[string]interface{} {
if args == nil {
return nil
}
if x,ok := args[0].(map[string]interface{}); ok {
return x
}
x := map[string]interface{}{}
for i := 0; i < len(args); i += 2 {
x[ args[i].(string) ] = args[i+1]
}
return x
}
func DoSomethingCool(x ...interface{}) {
args := parseArguments(x);
// args is now a map of type map[string]interface{}
}
You can now call DoSomethingCool()
in any of the following ways:
// No arguments
DoSomethingCool()
// These two are equivalent, and result in
// args = map[string]interface{}{
// "foo": "bar",
// "baz": "qux",
// }
DoSomethingCool(map[string]string{"foo": "bar", "baz": "qux"})
DoSomethingCool("foo","bar","baz","qux")
// Or you can even mix types for the keys, thanks to interface{}
// These two are also equivalents and result in
// args = map[string]interface{}{
// "foo": 20,
// "bar": false,
// }
DoSomethingCool(map[string]interface{}{"foo": 20, "bar": false})
DoSomethingCool("foo",20,"bar",false)
If you don't have a need to mix value types, you could just as well use map[string]string
I imagine.