如何在golang中解析多个返回

InA*_*ash 3 python return-value variadic go multiple-return-values

我有一个go函数,它返回两个整数值.以下是功能

func temp() (int, int){
 return 1,1
}
Run Code Online (Sandbox Code Playgroud)

是否可以将temp函数直接放入a Println并使用字符串格式打印输出,如下所示

fmt.Println("first= %d and second = %d", temp() ) // This doesn't work
Run Code Online (Sandbox Code Playgroud)

在Python中,我能够执行以下操作

def func():
    return 1,1
print("{0}={1}".format(*func())
>> '1=2'
Run Code Online (Sandbox Code Playgroud)

我可以在golang做类似的东西吗?

icz*_*cza 6

前言:我在 中发布了此实用程序github.com/icza/gox,请参阅gox.Wrap()


首先,对于您尝试执行的操作,您应该使用fmt.Printf()而不是fmt.Println()仅像前者所期望的那样使用格式字符串。

展望未来,这在默认情况下不受支持,因为引用自Spec: Calls:

作为一种特殊情况,如果一个函数或方法的返回值g在数量上相等并且可以单独分配给另一个函数或方法的参数f,那么调用f(g(parameters_of_g))f在将 的返回值绑定g到 的参数后调用f除了调用 之外, 的调用f不得包含任何参数g,并且g必须至少有一个返回值。如果f有一个最终...参数,则将其分配给g常规参数分配后剩余的返回值。

fmt.Printf()有以下签名:

func Printf(format string, a ...interface{}) (n int, err error)
Run Code Online (Sandbox Code Playgroud)

fmt.Printf()除了函数调用(调用的返回值)之外,您不能传递其他参数。

请注意,的签名fmt.Println()是:

func Println(a ...interface{}) (n int, err error)
Run Code Online (Sandbox Code Playgroud)

这意味着可以fmt.Println(temp())工作,对于任何其他至少具有一个返回值的函数也是如此,因为引用部分的最后一句允许这样做(“如果f有一个最终...参数,则g在分配常规参数。” )

但是通过一个小技巧,我们也可以实现您想要的fmt.Printf()

请注意,如果temp()将返回一个 type 值[]interface{},我们可以...将其作为某个可变参数的值传递。

这意味着这有效:

func main() {
    fmt.Printf("1: %v, 2: %v\n", temp()...)
}

func temp() []interface{} { return []interface{}{1, 2} }
Run Code Online (Sandbox Code Playgroud)

它可以正确打印(在Go Playground上尝试):

1: 1, 2: 2
Run Code Online (Sandbox Code Playgroud)

所以我们只需要一个实用函数,它将任何函数的返回值包装到 a 中[]interface{},这样我们就可以使用它来传递给fmt.Printf().

它非常简单:

func wrap(vs ...interface{}) []interface{} {
    return vs
}
Run Code Online (Sandbox Code Playgroud)

如上所述(使用fmt.Println()),我们可以将任何至少具有 1 个返回值的函数的返回值wrap()作为其输入参数的值传递。

现在使用这个wrap()函数,看下面的例子:

func main() {
    fmt.Printf("1: %v\n", wrap(oneInt())...)
    fmt.Printf("1: %v, 2: %v\n", wrap(twoInts())...)
    fmt.Printf("1: %v, 2: %v, 3: %v\n", wrap(threeStrings())...)
}

func oneInt() int { return 1 }

func twoInts() (int, int) { return 1, 2 }

func threeStrings() (string, string, string) { return "1", "2", "3" }
Run Code Online (Sandbox Code Playgroud)

这有效,并输出(在Go Playground上尝试):

1: 1
1: 1, 2: 2
1: 1, 2: 2, 3: 3
Run Code Online (Sandbox Code Playgroud)

有关该主题的更多信息,请参阅相关问题:

单值上下文中的多个值

在普通函数上返回像 Golang 中的“ok”这样的地图


mae*_*ics 5

不,这是不可能的.必须将多值表达式中的所有值分配给单独的变量才能使用它们,例如:

a, b := temp()
fmt.Println("first = %d and second = %d", a, b)
// first = 1 and second = 1
Run Code Online (Sandbox Code Playgroud)

[编辑]

有趣的是,在某些情况下,如果参数类型和arity匹配,或者对于纯粹的可变参数函数(Go Playground),在某些情况下,您可以使用多值表达式作为函数调用参数:

func oneTwo() (int, int) {
  return 1, 2
}

func incr2(x, y int) (int, int) {
  return x + 1, y + 1
}

func main() {
  incr2(oneTwo()) // OK: multi-value return and arguments match.

  fmt.Println(oneTwo()) // OK: pure variadic function.

  fmt.Printf("%d %d", oneTwo()) // ERR: mixed formal and variadic args.
}
Run Code Online (Sandbox Code Playgroud)