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