去命名参数

时间:2014-05-03 16:46:48

标签: python-3.x reflection go

如何将字典作为函数参数列表传递,如Go 3中的Python 3

Python 3:

def bar(a,b,c):
    print(a,b,c)

args={c: 1, b: 2, a: 3}
bar(**args)

空白:

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 ?
}

5 个答案:

答案 0 :(得分:18)

我不相信这是可能的。你需要使用一个结构来做任何事情,甚至远程接近这个(这是一个遥远的相似)

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)
}

答案 1 :(得分:10)

除了我认为无需重复的其他答案之外,请注意Go将自动解压缩具有多个返回参数的函数调用:

  1. 每个返回值都是函数的参数
  2. 每个参数都是函数的返回值
  3. (也就是说,函数参数列表的类型与其他函数的返回列表相同)。

    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())
    }
    

    将打印1,2,3。显然这个例子有点傻,但我发现这涵盖了大多数tuple和dict在Python中作为参数解包的情况,这往往是将一个函数的返回值作为另一个函数的参数传递的快速而肮脏的方式。

答案 2 :(得分:2)

为了完整起见,你既可以使用dskinner所说的内容,也可以使用"字典" (在Go中称为地图)您可以轻松使用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{})
}

答案 3 :(得分:1)

没有直接等同于Python的*args/**kwargs语法。您需要使用其他答案中列出的解决方案之一。

如果您只需传递未知数量的参数,则可以使您的函数variadic

package main

import (
    "fmt"
)

func bar(numbers ...int) {
    fmt.Printf("%d\n", numbers)
}

func main() {
    bar(3, 2, 1)       // prints [3 2 1]
    bar(5, 4, 3, 2, 1) // prints [5 4 3 2 1]
}

Play

答案 4 :(得分:1)

对于各种各样的值都没有经过彻底的测试,但它适用于一些简单的情况。随意扩展它以满足您的需求。它也不能保证是最好的方法,并且错误检查留给读者练习。

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{}
}

您现在可以通过以下任何方式致电DoSomethingCool()

// 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)

如果您不需要混合值类型,您也可以使用我想象的map[string]string