go语言求任意类型切片的长度

最近用 go 写程序时遇到一个问题——求任意类型切片的长度。作为一个初学者,刚刚学了接口和切片,知道了每个类型都实现了一个空接口 interface{},如果将接口类型作为函数的参数,那它应该是可以接收任意类型的实参的,带着这样的想法就写出了下面的代码:

func size(ins []interface{}) int {
        return len(ins)
}

然后调用

    a := []int{1, 2, 3, 4}
    fmt.Println(size(a))

但编译的时候报了以下错误:

    cannot use a (type []int) as type []interface {} in argument to size

从报错的信息来看,是 go 语言不支持将任意类型的切片转换为接口切片所导致的,为了确定是 go语言本身不支持所导致的以及探究不支持的原因,于是在网上查阅了一些资料,最权威的应该是来自于 go 的官方文档【https://github.com/golang/go/wiki/InterfaceSlice】。这上边的解释是说,由于非接口类型的切片与接口类型的切片在内存中的空间布局不一样,如果要做这样的隐式转换,将会比较耗时,因此 go 不支持此种转换。如果确实需要用到传接口切片的情况,则需要由程序员自己来提前做转换,在传参的时候确保实参是接口切片类型,这样才能通过编译,这也是官方推荐的做法,代码如下所示:

// 获得一个int类型的切片
var dataSlice []int = foo()
// 创建接口类型的切片
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
// 依次转换每个元素
for i, d := range dataSlice {
	interfaceSlice[i] = d
}
// 调用上面的size方法
size(interfaceSlice)

如果按照上面的写法来传参,那么求切片的长度就显得太费劲了,还不如直接调用 len(dataSlice) 完事。事情发展到这里,有点不甘心,于是继续查资料,发现 go 语言的反射机制可以解决这个问题。首先将上面的 size 函数的参数改为接口类型 (a interface{}),然后在里面用 reflect.TypeOf(a).Kind() 来判断实参的类型,如果是切片类型,则用 reflect.ValueOf() 来获得该切片,最后返回切片的长度,代码如下所示:

func Size(a interface{}) int {
        if reflect.TypeOf(a).Kind() != reflect.Slice {
                return -1
        }
        ins := reflect.ValueOf(a)
        return ins.Len()
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值