如何解析golang中的多个收益 [英] how to parse multiple returns in 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))
将调用f
将g
的返回值按顺序绑定到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
有关该主题的更多信息,请参见相关问题:
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 methodf
, then the callf(g(parameters_of_g))
will invokef
after binding the return values ofg
to the parameters off
in order. The call off
must contain no parameters other than the call ofg
, andg
must have at least one return value. Iff
has a final...
parameter, it is assigned the return values ofg
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屋!