日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Slice的本质

發布時間:2023/12/4 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Slice的本质 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Slice的本質

我們先看下面的代碼,看看它的輸出是什么:

package mainimport "fmt"type Slice []intfunc (A Slice) Append(value int) {A = append(A, value) } func main() {mSlice := make(Slice, 10, 20)mSlice.Append(5)fmt.Println(mSlice) } //output: [0 0 0 0 0 0 0 0 0 0]

我們查看append()前后變量的地址值:

func (A Slice) Append(value int) {A1 := append(A, value)fmt.Printf("&A = %p &A1 = %p\n", A, A1) } //output: &A = 0xc000114000 &A1 = 0xc000114000

所以說append()之后返回的Slice,是不是原來的Slice?

其實,我們在make一個Slice的時候可以傳遞三個參數:數據、長度和容量,這里就要提到SliceHeader。

SliceHeader是Slice運行時的具體表現,它的結構定義如下:

type SliceHeader struct {Data uintptr //指向底層數據源數組Len intCap int }

那么我們可以將Slice轉換為SliceHeader,再來看看A和A1內部的值是否一致。

func (A Slice) Append(value int) {A1 := append(A, value)sh := (*reflect.SliceHeader)(unsafe.Pointer(&A))fmt.Printf("A Data:%d,Len:%d,Cap:%d\n", sh.Data, sh.Len, sh.Cap)sh1 := (*reflect.SliceHeader)(unsafe.Pointer(&A1))fmt.Printf("A1 Data:%d,Len:%d,Cap:%d\n", sh1.Data, sh1.Len, sh1.Cap) } //output: A Data:824634474496,Len:10,Cap:20 // A1 Data:824634474496,Len:11,Cap:20

會發現它們的Len是不一樣的,所以不是同一個Slice,因此使用append()并沒有改變原來的A,而是生成了一個新的A1,A只在Append()內有效,mSlice并沒有發生改變。這里正確的做法是讓Append()返回append()之后的結果。

Append returns the updated slice. It is therefore necessary to store the result of append

上面的例子中,設置的Len是10和 Cap 是20,Cap足夠大,所以內置的append()并沒有生成新的底層數組。

mSlice := make(Slice, 10, 10)

再運行后發現兩個Slice的Data不再一樣:

//output: A Data:824633852064,Len:10,Cap:10 // A1 Data:824634187776,Len:11,Cap:20

這是因為在append()的時候,發現Cap不夠,生成了一個新的Data數組,用于存儲新的數據,并且同時擴充了Cap容量。

總結

以上是生活随笔為你收集整理的Slice的本质的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。