Go:记一次可变参数未展开踩坑
1.复现
原想要实现自己的错误函数test1280Error,生成带有固定前缀标识的error对象。
import "fmt"
func main() {
fmt.Println(test1280Error("msg: %s %s", "connection refused", "127.0.0.1:80"))
}
func test1280Error(format string, args ...interface{}) error {
return fmt.Errorf("test1280 error: "+format, args)
}
测试发现,在处理错误函数test1280Error可变参数时,输出和预期不一致:
实际输出:
$ go run main.go
test1280 error: msg: [connection refused 127.0.0.1:80] %!s(MISSING)
期望输出:
$ go run main.go
test1280 error: msg: connection refused 127.0.0.1:80
2.解决
修改test1280Error错误函数中args调用:
修改前:
func test1280Error(format string, args ...interface{}) error {
return fmt.Errorf("test1280 error: "+format, args)
}
修改后:
func test1280Error(format string, args ...interface{}) error {
return fmt.Errorf("test1280 error: "+format, args...)
}
3.原因
一时疏忽,在test1280Error错误函数中,没有正确展开可变参数args导致。
a.可以通过args[下标]来访问可变参数args指定下标元素,例如:
import "fmt"
func main() {
fmt.Println(test1280Error("msg: %s %s", "connection refused", "127.0.0.1:80"))
}
func test1280Error(format string, args ...interface{}) error {
return fmt.Errorf("test1280 error: "+format, args[0], args[1])
}
执行结果:
$ go run main.go
test1280 error: msg: connection refused 127.0.0.1:80
b.可以通过args…展开可变参数
上述方法行不通,因为args中参数数量在变化,因此不能显示指定args[0], args[1]…访问。
假设可变参数args分别是1,2,3,则:args[0]=1, args[1]=2, args[2]=3。
return fmt.Errorf("test1280 error: "+format, args[0], args[1], args[2])
可以使用如下代码替代:
return fmt.Errorf("test1280 error: "+format, args...)
args…将展开成为args[0], args[1], args[2],如同字符串替换一样。