前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Golang语言 - 以任意类型的slices作为输入参数

Golang语言 - 以任意类型的slices作为输入参数

作者头像
李海彬
发布2018-03-21 11:27:14
1.8K0
发布2018-03-21 11:27:14
举报
文章被收录于专栏:Golang语言社区Golang语言社区

最近参与的一个业余项目,go-linq,让我了解到Go语言的类型系统并不是为任何类面向 对象编程而设计的。没有泛型,没有类型继承,也没有提供任何对这些特性有用的东西。

但是,提供了一个名为interface{}的类型,你可以向其赋予几乎任意类型的值,不会抛出编译错误,就像.NET的Object或Java的Object:

var o interface{}

o := 3.14

o := Student{Name: "Ahmet"}

我们假设你需要一个可以接收任意类型slices的函数,如果考虑如下这样实现:

func Method(in []interface{}){...}

...

slice := []int{1, 2, 3}

Method(slice) // 抛出错误

这样的代码会抛出编译错误,因为[]int不是[]interface{}。那么该如何解决这个问题呢?你可以要求Method的使用者先把slices 转换为[]interface{}类型。也就是说他们必须借助于如下类似函数将他们的[]AnyType类型参数转换为[]interface{}类型:

代码语言:javascript
复制
func conv(in []AnyType) (out []interface{}) {
    out = make([]interface{}, len(in))
 for i, v := range in {
        out[i] = v
    }
 return
}
但这种实现的扩展性并不好。如果Method的使用者(可以是一个常用函数如Map、Filter等)想向Method传递N种不同类型的参数, 那么他们就必须编写N个conv函数。
对此,我们该怎么办呢?使用reflection(反射)呀!实现一个函数以interface{}(可以赋任意类型的值)为输入参数类型,在函数内部 将这个输入参数转换为一个slice,然后用于我们Method函数。如下所示:
func takeSliceArg(arg interface{}) (out []interface{}, ok bool) {
    slice, success := takeArg(arg, reflect.Slice)
 if !success {
        ok = false
 return
    }
    c := slice.Len()
    out = make([]interface{}, c)
 for i := 0; i < c; i++ {
        out[i] = slice.Index(i).Interface()
    }
 return out, true
}
func takeArg(arg interface{}, kind reflect.Kind) (val reflect.Value, ok bool) {
    val = reflect.ValueOf(arg)
 if val.Kind() == kind {
        ok = true
    }
 return
}

函数takeArg()尝试将传入的参数值转换为指定的reflect.Kind类型,然后函数takeSliceArg() 尝试将传递给它的值(经takeArg()转换后)转换为一个interface{}的slice。虽然,这样会因为反射而影响到一点性能,但影响并不大。

就是这样了。这种方案启发于Tobia Confronto的fn项目,并应用到go-linq中

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-05-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档