goLang实现不同类型的切片间互转

Posted 麦穗儿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了goLang实现不同类型的切片间互转相关的知识,希望对你有一定的参考价值。

golang的切片(slice)简单来说就是动态化的数组,切片的结构化定义如下

type SliceHeader struct {
    Data uintptr
    Len int
    Cap int 
}

C语言中可以使用不同类型的指针指向不同类型的结构来进行访问。例如可以使用指向char形的指针访问整形的数组。
对于goLang来说也可以实现不同类型切片间的互转,原理也是对SliceHeader结构体的指针Data进行赋值,同时对Len和Cap设置正确的值。

知道原理接下来说一些相关的反射机制

反射简单来说就是取得对象的类型(Type),类别(Kind),值(Value),对元素(Element)的字段(Field)进行遍历和操作(读写)。

对于类型(Type)和类别(Kind)需要注意一下。Type可以认为是Kind的子集
对于基本类型来说Type和Kind是一致的。例如int的Type和Kind一样都是int
对于Struct来说,Type是你定义的结构体, Kind为Struct

下面直接上代码,也比较好理解

func sliceConvert(origSlice interface{}, newSliceType reflect.Type) interface{} {
    sv := reflect.ValueOf(origSlice)
    if sv.Kind() != reflect.Slice {
        panic(fmt.Sprintf("Invalid origSlice(Non-slice value of type %T)", origSlice))
    }
    if newSliceType.Kind() != reflect.Slice {
        panic(fmt.Sprintf("Invalid newSliceType(non-slice type of type %T)", newSliceType))
    }

    //生成新类型的切片
    newSlice := reflect.New(newSliceType)

    //hdr指向到新生成切片的SliceHeader
    hdr := (*reflect.SliceHeader)(unsafe.Pointer(newSlice.Pointer()))

    var newElemSize = int(sv.Type().Elem().Size()) / int(newSliceType.Elem().Size())

    //设置SliceHeader的Cap,Len,以及数组的ptr
    hdr.Cap = sv.Cap() * newElemSize
    hdr.Len = sv.Len() * newElemSize
    hdr.Data = uintptr(sv.Pointer())

    return newSlice.Elem().Interface()
}

调用

    var int32Slice = []int32{1, 2, 3, 4, 5, 6, 7, 8}
    var byteSlice []uint8

    byteSlice = sliceConvert(int32Slice, reflect.TypeOf(byteSlice)).([]uint8)
    fmt.Println(byteSlice)

以上是关于goLang实现不同类型的切片间互转的主要内容,如果未能解决你的问题,请参考以下文章

Golang数据类型 切片(slice)

golang 基础 ——map数组切片 存放不同类型的数据

golang 基础 ——map数组切片 存放不同类型的数据

python中repr和eval可以用来在数据结构和字符串间互转

#yyds干货盘点#带大家认识Golang中的切片数据类型

Golang 函数传参使用切片而不使用数组为什么?