参数太灵活容易出错
(金庆的专栏 2020.7)
golang中可以将参数类型设为 interface{}, 这样就可以传入任意类型的参数,
和 C++ 中 void* 的作用相似。
但是这种万能类型应该尽量少用,尽量使用具体的类型,或者使用一个具体的接口类型。
主要的原因是, 让编译期的类型检查挡住编码错误,减少运行期的错误。
例如,go-mongo-driver 有个创建索引的参数:
```
type IndexModel struct {
// A document describing which keys should be used for the index. It cannot be nil.
// This must be an order-preserving type such as bson.D. Map types such as bson.M are not valid.
Keys interface{}
...
}
```
其中 Keys 可以是任意类型,如 1234, "abcd", 当然不符合索引要求的类型会返回失败。
但是 bson.M 类型,会创建索引成功,但是索引的次序会有错误。
注释中已指出,不要用 bson.M, 应该使用 bson.D.
正确的 Keys 如下,表示复合索引 (field1, field2),1表示正序,-1则反序:
```
indexModel.Keys := bson.D{{"field1", 1}, {"field2", 1}}
```
如果使用 bson.M, 实际上是个 map:
```
indexModel.Keys := bson.M{"field1":1, "field2": 1}
```
因为 map 成员的次序不定,最后创建的索引可能是 (field1, field2),也可能是 (field2, field1)。
此处类型允许 interface{} 的想法是,允许任意类型,会 bson 编码后传给 mongo 服务器,并不会进行类型检查。
这种灵活性非常容易造成错误,并且如何使用也不明确, 仅靠注释作用很小。