Go named arguments

huangapple go评论107阅读模式
英文:

Go named arguments

问题

在Go语言中,你可以使用结构体来模拟Python中的字典,并将其作为函数的参数传递。以下是一个示例:

type Args struct {
    A int
    B int
    C int
}

func bar(args Args) {
    fmt.Printf("%d, %d, %d", args.A, args.B, args.C)
}

func main() {
    args := Args{
        A: 3,
        B: 2,
        C: 1,
    }
    bar(args)
}

在这个示例中,我们定义了一个名为Args的结构体,它具有与Python字典中的键相对应的字段。然后,我们将Args结构体作为bar函数的参数传递,并在main函数中创建一个Args实例来传递参数。

请注意,Go语言中的结构体是一种更强大和灵活的数据结构,可以用于模拟Python中的字典以及其他更复杂的数据结构。

英文:

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

答案1

得分: 25

我不相信这是可能的。你需要使用一个结构体来实现与此类似的功能(尽管相似度很低)。

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)
}
英文:

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

答案2

得分: 15

除了其他答案之外,我看不需要重复,还要注意的是,Go语言会自动解包具有多个返回参数的函数调用:

  1. 每个返回值都是函数的参数
  2. 每个参数都是函数的返回值

也就是说,函数的参数列表的类型与其他函数的返回列表相同。

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。显然,这个例子有点傻,但我发现这种方式涵盖了Python中元组和字典解包作为参数的大多数情况,这往往是一种快速而简单的方式,将一个函数的返回值传递给另一个函数的参数。

英文:

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:

  1. Every return value is a parameter of the function
  2. Every parameter is a return value of the function

(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.

答案3

得分: 3

为了完整起见,你可以使用dskinner提到的方法,或者如果你想要一个“字典”(在Go中称为map),你可以很容易地使用一个,例如:

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

以上是你要翻译的内容。

英文:

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

答案4

得分: 2

Python的*args/**kwargs语法没有直接的等价物。你需要使用其他答案中概述的解决方案之一。

如果你只需要传递未知数量的参数,你可以将函数定义为可变参数函数。

package main

import (
	"fmt"
)

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

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

运行代码

英文:

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\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

答案5

得分: 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 现在是一个类型为 map[string]interface{} 的映射
}

现在你可以以以下任意方式调用 DoSomethingCool()

// 无参数
DoSomethingCool()

// 这两种方式是等价的,结果为
// args = map[string]interface{}{
// "foo": "bar",
// "baz": "qux",
// }
DoSomethingCool(map[string]string{"foo": "bar", "baz": "qux"})
DoSomethingCool("foo", "bar", "baz", "qux")

// 甚至可以混合使用不同类型的键,多亏了 interface{}
// 这两种方式也是等价的,结果为
// args = map[string]interface{}{
// "foo": 20,
// "bar": false,
// }
DoSomethingCool(map[string]interface{}{"foo": 20, "bar": false})
DoSomethingCool("foo", 20, "bar", false)

如果你不需要混合值类型,可以考虑使用 map[string]string

英文:

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 &lt; 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{}{
//     &quot;foo&quot;: &quot;bar&quot;,
//     &quot;baz&quot;: &quot;qux&quot;,
//  } 
DoSomethingCool(map[string]string{&quot;foo&quot;: &quot;bar&quot;, &quot;baz&quot;: &quot;qux&quot;})
DoSomethingCool(&quot;foo&quot;,&quot;bar&quot;,&quot;baz&quot;,&quot;qux&quot;)

// Or you can even mix types for the keys, thanks to interface{}
// These two are also equivalents and result in
// args = map[string]interface{}{
//     &quot;foo&quot;: 20,
//     &quot;bar&quot;: false,
//  } 

DoSomethingCool(map[string]interface{}{&quot;foo&quot;: 20, &quot;bar&quot;: false})
DoSomethingCool(&quot;foo&quot;,20,&quot;bar&quot;,false)

If you don't have a need to mix value types, you could just as well use map[string]string I imagine.

huangapple
  • 本文由 发表于 2014年5月4日 00:46:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/23447217.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定