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)