如何将多个返回值传递给可变参数函数? [英] How to pass multiple return values to a variadic function?

查看:83
本文介绍了如何将多个返回值传递给可变参数函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Go 函数,它返回两个整数值.下面是函数

func temp() (int, int){返回 1,1}

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

fmt.Println("first= %d and second = %d", temp() )//这不起作用

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

def func():返回 1,1打印("{0}={1}".format(*func())>>'1=2'

我也可以在 Go 中做类似的事情吗?

解决方案

前言: 我在 github.com/icza/gox,见 gox.Wrap().


首先,对于您尝试执行的操作,您应该使用 fmt.Printf() 而不是 fmt.Println() 因为只有前者需要并使用格式字符串.

今后,默认情况下不支持此功能,因为引用自 Spec: Calls:

<块引用>

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

并且 fmt.Printf() 有一个签名:

func Printf(format string, a ...interface{}) (n int, err error)

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

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

func Println(a ...interface{}) (n int, err 错误)

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

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

请注意,如果 temp() 将返回 []interface{} 类型的值,我们可以使用 ... 来传递它作为一些可变参数的值.

意味着这有效:

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

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

1: 1, 2: 2

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

而且非常简单:

func wrap(vs ...interface{}) []interface{} {回报 vs}

如上所述(使用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 { 返回 1 }func twoInts() (int, int) { return 1, 2 }func ThreeStrings() (string, string, string) { return 1", 2", 3";}

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

1: 11:1, 2:21:1, 2:2, 3:3

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

单值上下文中的多个值>

返回地图中的ok"Golang 在普通函数上

I have a Go function which returns two integer values. Below is the function

func temp() (int, int){
 return 1,1
}

Is it possible to put temp function directly into a Println and print both the outputs using string formatting as below:

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

In Python, I am able to do the following:

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

Can I do Something similar in Go too?

解决方案

Foreword: I released this utility in github.com/icza/gox, see gox.Wrap().


First, for what you attempt to do you should use fmt.Printf() instead of fmt.Println() as only the former expects and uses a format string.

Going forward, this isn't supported by default, because quoting from Spec: Calls:

As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call of f must contain no parameters other than the call of g, and g must have at least one return value. If f has a final ... parameter, it is assigned the return values of g that remain after assignment of regular parameters.

And fmt.Printf() has a signature of:

func Printf(format string, a ...interface{}) (n int, err error)

You cannot pass other parameters to fmt.Printf() besides a function call (the return values of the call).

Note that the signature of fmt.Println() is:

func Println(a ...interface{}) (n int, err error)

Which means that fmt.Println(temp()) works, and so does with any other functions that have at least one return value, because the last sentence of the quoted part allows this ("If f has a final ... parameter, it is assigned the return values of g that remain after assignment of regular parameters.")

But with a little trick we can achieve what you want with fmt.Printf() too.

Note that if temp() would return a value of type []interface{}, we could use ... to pass it as the value of some variadic parameter.

Meaning this works:

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

func temp() []interface{} { return []interface{}{1, 2} }

And it properly prints (try it on the Go Playground):

1: 1, 2: 2

So we just need a utility function that wraps the return values of any function into a []interface{}, and so we can use this to pass to fmt.Printf().

And it's dead-simple:

func wrap(vs ...interface{}) []interface{} {
    return vs
}

As detailed above (with fmt.Println()), we can pass the return values of any function that has at least 1 return value to wrap() as the values of its input parameters.

Now using this wrap() function, see the following example:

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

This works, and it outputs (try it on the Go Playground):

1: 1
1: 1, 2: 2
1: 1, 2: 2, 3: 3

For more on the topic, see related question:

Multiple values in single-value context

Return map like 'ok' in Golang on normal functions

这篇关于如何将多个返回值传递给可变参数函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆