日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

golang中slice切片使用的誤區

作者:鐵柱同學 更新時間: 2022-07-26 編程語言

一、前言

??????最近在項目代碼中,發現了一種寫法,如下所示:

//期望是能把id順序寫到切片,把切片占滿,元素數為10個
Ids1 := make([]int64, 10)
for _, v := range xxxx {
   Ids1 = append(Ids1, v.ids1)
}

??????看起來還可以,提前給切片分配長度,防止append頻繁擴容。然而在實際使用中才發現,以上結果打印如下:

Ids1:([0 0 0 0 0 0 0 0 0 0 393 394 395 396 397 398 399 400 401 402])

??????是不是跟想象中不一樣,這特么的不是說好的分配長度,使用已有長度,怎么打印出來的是0,而且切片依然發生了擴容。

二、切片分配長度的正確用法

1、切片的初始化

??????博主百思不得其解,于是去百度切片的用法,發現一般初始化切片如下:

make([]T, len)   //省略cap,len=cap
make([]T, len, cap) // 等價于 make([]T, cap)[:len]

使用make初始化,由于未賦值系統默認將元素值置為0,即:

數值類型數組:   默認值為0
字符串數組:     默認值為""
bool數組:      默認值為false

那么我們打印出來的0值,是否就是被make初始化零值的原因呢?

2、打印切片長度和容量

	Ids1 := make([]int64, 10)
	fmt.Println("Ids1切片長度:", len(Ids1))
	fmt.Println("Ids1切片容量:", cap(Ids1))
	fmt.Println("Ids1切片內容:", Ids1)
	Ids2 := make([]int64, 0, 10)
	fmt.Println("Ids2切片長度:", len(Ids2))
	fmt.Println("Ids2切片容量:", cap(Ids2))
	fmt.Println("Ids2切片內容:", Ids2)

結果如下:

Ids1切片長度: 10
Ids1切片容量: 10
Ids1切片內容: [0 0 0 0 0 0 0 0 0 0]
Ids2切片長度: 0
Ids2切片容量: 10
Ids2切片內容: []

??????通過打印結果我們發現,第一種初始化的方式,同時定義了lencap,導致切片默認分配了零值,當我們使用append的時候,由于新元素超過了cap(10),因此就發生了擴容,導致寫入的元素堆到了后面。

??????第二種初始化的方式,我們定義了cap,但是len=0,這樣就不會默認給元素賦零值,因為切片實際上是沒有任何元素的。此時append就可以把元素加進去,填充切片。

3、正確的用法

(1)下標指定

Ids1 := make([]int64, 10)
for k, v := range xxxx {
   Ids1[k] =  v.ids1
}

(2) 使用另一種初始化方式

Ids1 := make([]int64, 10)
Ids2 := make([]int64, 0, 10)
for _, v := range xxxx {
   Ids1 = append(Ids1, v.ids1)
   Ids2 = append(Ids2, v.ids2)
}

//打印結果如下:
 
 Ids1:([0 0 0 0 0 0 0 0 0 0 393 394 395 396 397 398 399 400 401 402])
 Ids2:([183 184 184 185 185 186 187 188 189 190])

??????看似簡單的代碼,實際上也暗藏玄機。博主一開始也被誤導了,代碼看似提前分配了容量,實際上沒鳥用,擴容跑不了,而且前10個元素為0,這個時候萬一靠下標獲取元素,直接出bug沒商量。

end

原文鏈接:https://blog.csdn.net/LJFPHP/article/details/125826204

欄目分類
最近更新