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

最近参与的一个业余项目,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{}类型:

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中

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2016-05-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏python3

python3--面向对象进阶之内置方法

print执行时,是去内部寻找__str__方法,所以print没有输出不了的数据,因为每一个对象都有__str__方法

9610
来自专栏C/C++基础

C++引用计数(reference counting)技术简介(3)

要想将引用计数施加到现有的实值对象Widget上,按照前面讨论的,都需要修改Winget类的源代码。但是,有时程序库的内容不是我们呢可以修改的,又该如何做呢?

8210
来自专栏Python中文社区

Python迭代器使用详解

这一集的内容看起来比较绕,反反复复出现的是迭代二字。大家注意,这一节的内容很pythonic,是很有特色也非常重要的知识点。敲黑板啦!

14200
来自专栏GreenLeaves

字符、字符串和文本的处理之String类型

13320
来自专栏灯塔大数据

技术 | Python从零开始系列连载(十一)

导读 为了解答大家初学Python时遇到各种常见问题,小灯塔特地整理了一系列从零开始的入门到熟练的系列连载,每周五准时推出,欢迎大家学积极习转载~ 上一期学习了...

407100
来自专栏老马说编程

(24) 异常 (上) / 计算机程序的思维逻辑

之前我们介绍的基本类型、类、接口、枚举都是在表示和操作数据,操作的过程中可能有很多出错的情况,出错的原因可能是多方面的,有的是不可控的内部原因,比如内存不够了、...

17560
来自专栏每日一篇技术文章

Swift3.0 - 流控制

需求二: 输入一个顶点 判断是否在X轴上,或者Y轴上,或者既不在x轴,也不再Y轴上

8820
来自专栏Python自动化测试

python的set集合学习(七)

在python中,set集合是一个无序并且不重复的元素集合,它的关键字是set,依然按照之前的思维方式,我们定义一个set集合,来看它的类所具备的功...

14330
来自专栏星汉技术

Java API:Object class

16870
来自专栏用户2442861的专栏

JAVA反射机制作用是什么

Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对大家以后学习框架技术有很大的帮助。

1.8K20

扫码关注云+社区

领取腾讯云代金券