//定义切片类型
type Slice struct {
// void * C语言中的万能指针,没有具体数据类型,不能进行运算
Data unsafe.Pointer //go语言中万能指针类型。操作需要转换成int
Len int //数据元素个数
Cap int //可扩展的有效容量
}
unsafe.Pointer参与运算操作需要转换,
p := uintptr(unsafep)
申请内存
int main(void)
{
//申请内存
int *p = (int *)malloc(100);
*p = 666
//扩展内存空间
int *q = realloc(p, 200);
//释放内存空间
free(p);
return 0
}
/*
#include
*/
切片对象操作方法
1.创建切片Create(长度,容量,数据)
2.打印切片Print()
3.追加元素Append(数据)
4.获取元素GetData(下标) int
5.查找元素SearchData(数据) 下标
6.删除元素Delete(下标)
7.销毁切片Destroy()
8.插入元素Insert(数据,下标)
创建切片
func (s *Slice) Create(l int, c int, Data ...int) {
//1.容错处理,加强代码健壮性
if s == nil || Data == nil {
return
}
if len(Data) == 0 {
return
}
if l < 0 || c < 0 || l > c || len(Data) > l {
return
}
//2.申请内存空间
s.Data = C.malloc(C.size_t(c) * 8)
//3.初始化长度和容量
s.Len = l
s.Cap = c
//4.将s.Data转换成可以计算的数值(地址)
p := uintptr(s.Data)
//5.根据Data集合,遍历存入申请的内存中
for _, v:= range Data {
*(*int)(unsafe.Pointer(p)) = v
//指针偏移8
p += 8
}
}
打印切片
func (s *Slice) Print() {
if s == nil {
return
}
//将地址转换为可以计算的数值
p := uintptr(s.Data)
//循环打印
for i := 0; i < s.Len; i++ {
fmt.Print(*(*int)(unsafe.Pointer(p)), " ")
p += TAG
}
fmt.Println()
}
追加元素
func (s *Slice) Append(Data ...int) {
if s == nil {
return
}
// 判断是否需要扩容
for len(Data)+s.Len > s.Cap {
// 拓展容量为原来的 2 倍, 存储新内存空间地址
s.Data = C.realloc(s.Data, C.size_t(s.Cap)*2*8)
s.Cap *= 2
}
// 将s.Data 转换程可以运算的 数值
p := uintptr(s.Data)
/* for i:=0; i
根据下标获取元素
//根据切片下标取元素
func (s *Slice) GetData(index int) int {
if s == nil {
return -1
}
if index < 0 || index >= s.Len {
return -1
}
// 将 万能指针转换为可以计算的 数据
p := uintptr(s.Data)
// 偏移p,到 index 指代的元素位置
p += uintptr(index) * TAG
// 取数据值,返回
return *(*int)(unsafe.Pointer(p))
}
已知元素,获取下标
// 已知元素,返回下标值
func (s *Slice) SearchData(Data int) int {
if s == nil {
return -1
}
// 将万能指针,转换为可以计算的数据值
p := uintptr(s.Data)
for i := 0; i < s.Len; i++ {
if *(*int)(unsafe.Pointer(p)) == Data {
return i
}
p += TAG
}
return -1
}
根据下标,删除切片元素
// 根据下标,删除切片元素
func (s *Slice) Delete(index int) {
if s == nil {
return
}
if index < 0 || index >= s.Len {
return
}
// 将万能指针,转换为可以计算的数据值
p := uintptr(s.Data)
// 将p 偏移到 index 位置
p += uintptr(index) * TAG
// 定义 变量,记录 p 指代的元素的 下一个元素
aftp := p
// 循环从 index 到 s.Len 依次完成 后一个元素给前一个元素赋值
for i := index; i < s.Len; i++ {
aftp += TAG
*(*int)(unsafe.Pointer(p)) = *(*int)(unsafe.Pointer(aftp))
p += TAG
}
// 修改 s.Len 去除一个元素
s.Len -= 1
}
插入元素
// 根据index ,向 切片插入数据
func (s *Slice) Insert(Data int, index int) {
if s == nil {
return
}
if index < 0 || index > s.Len {
return
}
// 如果 插入的index 在切片结尾
if index == s.Len {
s.Append(Data)
return
}
// 判断是否超出cap
// 如果插入位置 在 中间
p := uintptr(s.Data)
// 将p偏移到 index 位置
p += uintptr(index) * TAG
// 获取插入元素完成后的,最后一个元素位置.
temp := uintptr(s.Data) + uintptr(s.Len) * TAG
// 循环将 index 之后的元素依次后移(前一个元素,给后一个元素赋值)
for i := s.Len; i > index; i-- {
*(*int)(unsafe.Pointer(temp)) = *(*int)(unsafe.Pointer(temp-TAG))
temp -= TAG
}
// 循环结束后,将 p 对应的内存,写入 参数 Data
*(*int)(unsafe.Pointer(p)) = Data
// 修改 s.Len
s.Len++
}
销毁切片 Destroy
// 销毁 切片
func (s *Slice) Destroy() {
if s == nil || s.Data == nil {
return
}
C.free(s.Data)
s.Data = nil // 驱使go GC工作
s.Len = 0
s.Cap = 0
s = nil
runtime.GC() // 手动调用 GC
}