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 = https://www.cnblogs.com/lurenq/p/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 = https://www.cnblogs.com/lurenq/p/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}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/53030.html
標籤:Go
上一篇:Golang中類面向物件特性
下一篇:單向鏈表實作原理
