如何解析golang中的多个收益 [英] how to parse multiple returns in golang

查看:76
本文介绍了如何解析golang中的多个收益的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

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

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

我还能在Go中做类似的事情吗?

解决方案

前言:我在 gox.Wrap() .


首先,对于您尝试执行的操作,应使用 fmt.Printf() 代替 fmt.Println() ,只有前者期望并使用格式字符串.

展望未来,默认情况下不支持此操作,因为引用自规格:调用:

在特殊情况下,如果一个函数或方法g的返回值数量相等并且可以分别分配给另一个函数或方法f的参数,则调用f(g(parameters_of_g))将调用fg的返回值按顺序绑定到f的参数后. 调用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 error)

这意味着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} }

它可以正确打印(在游乐场上尝试):

1: 1, 2: 2

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

这简直太简单了:

func wrap(vs ...interface{}) []interface{} {
    return 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 { return 1 }

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

func threeStrings() (string, string, string) { return "1", "2", "3" }

这有效,并输出(在游乐场上尝试):

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

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

在单值上下文中有多个值

在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

这篇关于如何解析golang中的多个收益的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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