我有一个Go函数,它返回两个整数值。下面是功能
func temp() (int, int){ return 1,1 }
是否可以将temp函数直接放入a Println并使用以下字符串格式打印两个输出:
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中做类似的事情吗?
前言: 我在中发布了此实用程序github.com/icza/gox,请参见builtinx.Wrap()。
github.com/icza/gox
builtinx.Wrap()
首先,对于您尝试执行的操作,应该使用fmt.Printf()而不是fmt.Println()仅按照前者的预期使用并使用格式字符串。
fmt.Printf()
fmt.Println()
展望未来,默认情况下不支持此操作,因为从Spec:Calls中引用:
作为一种特殊情况,如果一个函数或方法的返回值g数量相等并且可以分别分配给另一个函数或方法的参数f,则该调用f(g(parameters_of_g))将在按顺序f将返回值绑定g到参数之后调用f。 的调用f除的调用外不得包含任何参数g,并且g必须至少具有一个返回值。如果f具有最终...参数,则分配g常规参数后保留的返回值。
g
f
f(g(parameters_of_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.Println(temp())
但是,通过一些技巧,我们也可以实现您想要的fmt.Printf()。
请注意,如果temp()将返回type的值[]interface{},我们可以...将其用作某些可变参数的值。
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{} { return vs }
如上文所述(使用fmt.Println()),我们可以将至少具有1个返回值的任何函数的返回值wrap()作为其输入参数的值传递。
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