Go - 以任意类型的slices作为输入参数

Go - 以任意类型的slices作为输入参数(译)

2014-01-16 Thu

By youngsterxyf

原文:Go – taking slices of any type as input parameters

译者:youngsterxyf

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

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

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{}类型:

func conv(in []AnyType) (out []interface{}) {

    out = make([]interface{}, len(in))

    for i, v := range in {

        out[i] = v

    }

    return

}

但这种实现的扩展性并不好。如果Method的使用者(可以是一个常用函数如MapFilter等)想向Method传递N种不同类型的参数, 那么他们就必须编写Nconv函数。

对此,我们该怎么办呢?使用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 Confrontofn项目,并应用到go-linq

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值