slice 实现原理
程序员文章站
2022-05-29 08:05:59
package main /* #include */ import "C" import ( "unsafe" "fmt" ) type Slice struct { Data unsafe.Pointer //万能指针类型 对应C语言中的void* len int //有效... ......
package main
/*
#include <stdlib.h>
*/
import "c"
import (
"unsafe"
"fmt"
)
type slice struct {
data unsafe.pointer //万能指针类型 对应c语言中的void*
len int //有效的长度
cap int //有效的容量
}
const tag = 8
/*
func main() {
//定义一个切片
//1、数据内存地址 2、len 有效数据长度 3、cap 可扩容的有效容量 24字节
var s []int
//unsafe.sizeof 计算数据类型在内存中占的字节大小
fmt.println(unsafe.sizeof(s))
}
*/
/*
func main(){
var i interface{}
i=10//只支持== !=
//类型断言 是基于接口类型数据的转换
//value,ok:=i.(int)
//if ok{
// fmt.println("整型数据:",value)
// fmt.printf("%t\n",value)
//}
//反射获取接口的数据类型
//t:=reflect.typeof(i)
//fmt.println(t)
//反射获取接口类型数据的值
v:=reflect.valueof(i)
fmt.println(v)
i1:=10
i2:=20
if reflect.typeof(i1)==reflect.typeof(i2){
v1:=reflect.valueof(i1)
v2:=reflect.valueof(i2)
结果=v1+v2
}
}
*/
//create(长度 容量 数据)
func (s *slice) create(l int, c int, data ...int) {
//如果数据为空返回
if len(data) == 0 {
return
}
//长度小于0 容量小于0 长度大于容量 数据大于长度
if l < 0 || c < 0 || l > c || len(data) > l {
return
}
//ulonglong unsigned long long 无符号的长长整型
//通过c语言代码开辟空间 存储数据
//如果堆空间开辟失败 返回值为null 相当于nil 内存地址编号为0的空间
s.data = c.malloc(c.ulonglong(c) * 8)
s.len = l
s.cap = c
//转成可以计算的指针类型
p := uintptr(s.data)
for _, v := range data {
//数据存储
*(*int)(unsafe.pointer(p)) = v
//指针偏移
p += tag
//p+=unsafe.sizeof(1)
}
}
//print 打印切片
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
}
}
//切片追加
func (s *slice) append(data ...int) {
if s == nil {
return
}
if len(data) == 0 {
return
}
//如果添加的数据超出了容量
if s.len+len(data) > s.cap {
//扩充容量
//c.realloc(指针,字节大小), go 语言 2 倍扩容。
s.data = c.realloc(s.data, c.ulonglong(s.cap)*2*8)
//改变容量的值
s.cap = s.cap * 2
}
p := uintptr(s.data)
for i := 0; i < s.len; i++ {
//指针偏移
p += tag
}
//添加数据
for _, v := range data {
*(*int)(unsafe.pointer(p)) = v
p += tag
}
//更新有效数据(长度)
s.len = s.len + len(data)
}
//获取元素 getdata(下标) 返回值为int 元素
func (s *slice) getddata(index int) int {
if s == nil || s.data == nil {
return 0
}
if index < 0 || index > s.len-1 {
return 0
}
p := uintptr(s.data)
for i := 0; i < index; i++ {
p += tag
}
return *(*int)(unsafe.pointer(p))
}
//查找元素 search(元素)返回值为int 下标
func (s *slice) search(data int) int {
if s == nil || s.data == 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
}
//删除元素 delete(下标)
func (s *slice) delete(index int) {
if s == nil || s.data == nil {
return
}
if index < 0 || index > s.len-1 {
return
}
//将指针指向需要删除的下标位置
p := uintptr(s.data)
for i := 0; i < index; i++ {
p += tag
}
//用下一个指针对应的值为当前指针对应的值进行赋值
temp := p
for i := index; i < s.len; i++ {
temp += tag
*(*int)(unsafe.pointer(p)) = *(*int)(unsafe.pointer(temp))
p += tag
}
s.len--
}
//插入元素 insert(下标 元素)
func (s *slice) insert(index int, data int) {
if s == nil || s.data == nil {
return
}
if index < 0 || index > s.len-1 {
return
}
//如果插入数据是最后一个
//if index == s.len-1 {
// p := uintptr(s.data)
//
// //for i := 0; i < s.len; i++ {
// // p += tag
// //}
// p += tag * uintptr(s.len-1)
// *(*int)(unsafe.pointer(p)) = data
// s.len++
// return
//}
//调用追加方法
if index == s.len-1 {
s.append(data)
return
}
//获取插入数据的位置
p := uintptr(s.data)
for i := 0; i < index; i++ {
p += tag
}
//获取末尾的指针位置
temp := uintptr(s.data)
temp += tag * uintptr(s.len)
//将后面数据依次向后移动
for i := s.len; i > index; i-- {
//用前一个数据为当前数据赋值
*(*int)(unsafe.pointer(temp)) = *(*int)(unsafe.pointer(temp - tag))
temp -= tag
}
//修改插入下标的数据
*(*int)(unsafe.pointer(p)) = data
s.len++
}
//销毁切片
func (s *slice) destroy() {
//调用c语言 适释放堆空间
c.free(s.data)
s.data = nil
s.len = 0
s.cap = 0
s = nil
}
上一篇: css之文本两端对齐
下一篇: 爬虫(十一):selenium爬虫