本文首发于我的Github博客
本文记录了作者在使用goland提供的提取方法(Extract Method)功能时,由于...interface{}的类型问题而遭遇到的bug和一点感悟,简单来说:
- 可变长的参数会被goland的Extract Method转化为切片(slice),比如
...interface{}会被转化为[]interface{} - 由于
interface{}的特殊性,需要额外注意
bug的产生
在代码中有如下片段
func f(payload ...interface{}) {
for _, p := range payload {
// do something
}
}
现在想要将循环提取出来,作为一个方法,在goland中可以直接选中文本然后Extract Method,但是结果是这样的
func f(payload ...interface{}) {
ExtractedMethod(payload)
}
func ExtractedMethod(payload []interface{}) {
for _, p := range payload {
// do something
}
}
期望中的函数签名是ExtractedMethod(payload ...interface{}),不符合预期,所以要进行修改
// WRONG!!!!!!!!
func f(payload ...interface{}) {
ExtractedMethod(payload)
}
func ExtractedMethod(payload ...interface{}) {
for _, p := range payload {
// do something
}
}
上述的代码不会有编译错误,但是是完全不符合预期的,为什么呢?
bug的原因
// WRONG!!!!!!!!
func f(payload ...interface{}) {
// we need to unpack payload
ExtractedMethod(payload)
}
func ExtractedMethod(payload ...interface{}) {
for _, p := range payload {
// do something
}
}
如上述注释所说,我们需要对f中传递给ExtractedMethod的参数payload做一个解包工作,因为
- 我们
f函数的本意是要用ExtractedMehtod对payload中的每一个元素做处理 - 现在不解包,
payload原本一个[]interface{}又被额外自动包装了一层,成为了interface{}传递给了ExtractedMethod,只会对整个payload做一次处理
bug的解决与思考
将代码修改为如下后正确
func f(payload ...interface{}) {
ExtractedMethod(payload...)
}
func ExtractedMethod(payload ...interface{}) {
for _, p := range payload {
// do something
}
}
以后可以采取的方法是,先将传参的地方payload改为payload...,这样的话如果忘记修改参数[]interface{}为...interface{},是会有编译器报错的
这个修改顺序可以让编译器为我们保驾
本文讲述了作者在Goland中使用Extract Method功能时遇到的问题,由于interface{}类型导致的bug及其解决思路。当可变长参数被转换为slice,可能会引发预期不符。解决方案是确保对interface{}参数进行解包,以避免只处理整个slice而非单个元素。
1030

被折叠的 条评论
为什么被折叠?



