问题起因
由于缺乏泛型机制,所以公共方法的返回值不好处理。
这里贴一个自己的实现,有更好的改进方案欢迎留言。
具体实现1
func version1(params ...interface{}) []interface{} {
cache := make(map[interface{}]int)
for _, param := range params {
switch reflect.TypeOf(param).Kind() {
case reflect.Slice:
slice := reflect.ValueOf(param)
for i := 0; i < slice.Len(); i++ {
eachItem := slice.Index(i).Interface()
cache[eachItem]++
}
}
}
ans := make([]interface{}, 0)
for key, val := range cache {
if val == len(params) {
ans = append(ans, key)
}
}
return ans
}
优点
直接返回interface
的切片,处理简单。
不足
使用起来不那么方便,需要额外的类型转换。
具体实现2
func version2(ans interface{}, params ...interface{}) {
if reflect.TypeOf(ans).Kind() != reflect.Ptr ||
reflect.TypeOf(ans).Elem().Kind() != reflect.Slice {
panic(fmt.Sprintf("ans type error %T", ans))
}
cache := make(map[interface{}]int)
for _, param := range params {
switch reflect.TypeOf(param).Kind() {
case reflect.Slice:
slice := reflect.ValueOf(param)
for i := 0; i < slice.Len(); i++ {
eachItem := slice.Index(i).Interface()
cache[eachItem]++
}
}
}
v := reflect.ValueOf(ans).Elem()
var i int
for key, val := range cache {
if i >= v.Cap() {
newcap := v.Cap() + v.Cap()/2
if newcap < 4 {
newcap = 4
}
newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
reflect.Copy(newv, v)
v.Set(newv)
v.SetLen(newcap)
v.SetCap(newcap)
}
if val == len(params) {
v.Index(i).Set(reflect.ValueOf(key))
i++
}
}
v.Set(v.Slice(0, i))
}
优点
参考标准库中json
解析部分的实现方式,将返回值指针当做参数的一部分,使用起来方便些。
不足
由于变参语法限制,返回值指针只能作为第一个参数,不太符合习惯。
具体实现3
func version3(params ...interface{}) {
var ans interface{}
cache := make(map[interface{}]int)
for _, param := range params {
switch reflect.TypeOf(param).Kind() {
case reflect.Slice:
slice := reflect.ValueOf(param)
for i := 0; i < slice.Len(); i++ {
eachItem := slice.Index(i).Interface()
cache[eachItem]++
}
case reflect.Ptr:
ans = param
}
}
if ans == nil ||
reflect.TypeOf(ans).Elem().Kind() != reflect.Slice {
panic(fmt.Sprintf("ans type error %T", ans))
}
v := reflect.ValueOf(ans).Elem()
var i int
for key, val := range cache {
if i >= v.Cap() {
newcap := v.Cap() + v.Cap()/2
if newcap < 4 {
newcap = 4
}
newv := reflect.MakeSlice(v.Type(), v.Len(), newcap)
reflect.Copy(newv, v)
v.Set(newv)
v.SetLen(newcap)
v.SetCap(newcap)
}
if val == len(params)-1 {
v.Index(i).Set(reflect.ValueOf(key))
i++
}
}
v.Set(v.Slice(0, i))
}
优点
改进了之前的问题,现在返回值可以在任意位置了。
测试代码
import (
"fmt"
"reflect"
)
func main() {
fmt.Println(version1([]int{1, 2, 3, 4, 5}, []int{2, 3, 4}, []int{3}))
var ans2 []int
version2(&ans2, []int{1, 2, 3, 4, 5}, []int{2, 3, 4}, []int{3})
fmt.Println(ans2)
var ans3 []int
version3(&ans3, []int{1, 2, 3, 4, 5}, []int{2, 3, 4}, []int{3})
fmt.Println(ans3)
}
测试结果
[3]
[3]
[3]