问题
今天在做LeetCode时,需要一个函数delChar,用于把一个字符串中的指定字符删除掉:
1 | func DelChar(s string, char byte) string { |
然后我突发奇想:如果有一个函数,接收任意的数组类型,删除其等于指定值的所有元素,那岂不很方便.说干就干!
1 | func DeleteElement(array []interface{}, element interface{}) []interface{} { |
嗯,看上去很完美,然后运行:
1 | DeleteElement("1234512345",'1') |
输出:
./hello.go:5:23: cannot use s (type string) as type []interface {} in argument to DeleteElement
嗯…string类型不能转换为[]interface{}
类型,那换字节切片看看:
1 | DeleteElement([]byte("1234512345"),'1') |
输出:
./hello.go:4:30: cannot use ([]byte)("1234512345") (type []byte) as type []interface {} in argument to DeleteElement
也不行,这是为什么呢?如果这两种类型都不能转换为[]interface{}
类型,那还有什么类型能转换的么,直接用[]interface{}
类型试试?
1 | inter:=make([]interface{},3) |
输出:
[hello 1.1]
终于成功了…不过这么看来,[]interface{}
只能接受和它相同的类型才行,这有什么用?在网上查了资料,解释如下:
[]interface{}
类型并非interface{}
类型,它实际上是一个每个元素都是interface{}
类型的切片.因此不能将其他类型如string
,[]byte
复制给[]interface{}
- 每个
interface{}
类型都占用2个字(WORD),一个字存储其底层变量的类型,另一个字存储其底层变量的值.一个长度为n的[]interface{}
变量的大小为2*n
个字;而[]MyType的大小则为sizeof(MyType)*n
.两者长度不相同,因此不能转换
在我看来,[]byte
(示例)类型不能转换为[]interface{}
类型的原因还有一点:[]byte
类型可以表示为interface{}
类型,如果它还能转换为[]interface{}
类型的话,那么编译器就不知道它到底该转换成什么类型了
值得一提的是,像其它所有类型一样,[]interface{}
也可以转换为interface{}
类型
解决方案
那么,如果真的想要写这样一个函数,该怎么写呢?
一个想法是使用可变参数函数,尽可能避免使用[]interface{}
类型
1 | func DeleteElement(element interface{}, array ...interface{}) []interface{} { |
然而返回值貌似还得是[]interface{}
…这种返回值看来只能一个个将里面的元素转换为其他类型了
小结
记得之前看过一篇文章说过,interface{}
类型像是golang中的潘多拉魔盒,给开发者带来强大力量的同时也留下无穷后患.对于golang这种强类型语言来说,interface{}
这种近乎动态的万能类型还是用得越少越好