一尘不染

如何解析golang中的多个收益

go

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

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

是否可以将temp函数直接放入a 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中做类似的事情吗?


阅读 196

收藏
2020-07-02

共1个答案

一尘不染

前言:
我在中发布了此实用程序github.com/icza/gox,请参见builtinx.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)

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

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

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

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

并正确打印(在Go Playground上尝试):

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

这可行,并且输出(在Go Playground上尝试):

1: 1
1: 1, 2: 2
1: 1, 2: 2, 3: 3
2020-07-02