前言:我在github.com/icza/gox
上发布了这个实用程序,请查看gox.Wrap()
。
首先,为了实现您想要的功能,应该使用fmt.Printf()
而不是fmt.Println()
,因为只有前者期望并使用格式化字符串。
从现在开始,默认情况下不支持此操作,因为引用自规范:调用:
特殊情况下,如果函数或方法 g
的返回值数量相等且可以单独分配给另一个函数或方法 f
的参数,则调用 f(g(g的参数))
将绑定 g
的返回值按顺序分配给 f
的参数以后调用 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} }
它可以正确地输出(在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
更多相关内容请参见:
在单值上下文中使用多个值
如何在Go中的普通函数中返回类似于map的“ok”值