數(shù)組
定義
數(shù)組是固定長度的特定元素類型的序列
特點
- 長度固定,初始化時長度可以用...代替口四,標識根據(jù)數(shù)組數(shù)據(jù)計算其長度孵运,也可以是一個常量值;不可以對數(shù)組進行增刪操作蔓彩。
- 長度是數(shù)組類型的一部分治笨,[3]int和[5]int是兩種不同的類型
- 數(shù)組是值傳遞的,函參數(shù)組是數(shù)組值的復制赤嚼。
應用場景
數(shù)組在golang中的使用場景較少旷赖。一般只在數(shù)組長度確定并且不發(fā)生變更的情況下會使用數(shù)組,此時要比使用切片性能更優(yōu)更卒。例如等孵,存儲excel文件解析時列字段順序枚舉。
切片
定義
切片是不定長的特定元素類型的序列
特點
- 切片的長度是不固定的蹂空,可以針對切片進行添加和截取操作俯萌。
- 切片的底層實現(xiàn)是一個結構體,包括長度上枕、容量和一個指向?qū)嶋H數(shù)組的unsafe.Pointer指針绳瘟。
type slice struct {
array unsafe.Pointer
len int
cap int
}
- 淺拷貝:長度是切片實際存儲元素的個數(shù),容量是切片目前可以存儲元素的個數(shù)姿骏,長度<容量糖声,當操作切片大于容量時,會產(chǎn)生數(shù)組越界的panic。
- 深拷貝:切片的淺拷貝是底層匿名數(shù)組的引用的復制蘸泻,非擴容情況下任何一個拷貝值發(fā)生變化琉苇,所有切片均會發(fā)生變化
func main() {
// 切片實質(zhì)上是對底層匿名數(shù)組的引用
slice := make([]int, 5, 5)
slice1 := slice
slice2 := slice[:]
slice3 := slice[0:4]
slice4 := slice[1:5]
slice[1] = 1
fmt.Println(slice)//[0 1 0 0 0]
fmt.Println(slice1)//[0 1 0 0 0]
fmt.Println(slice2)//[0 1 0 0 0]
fmt.Println(slice3)//[0 1 0 0]
fmt.Println(slice4)//[1 0 0 0]
}
- 切片的深拷貝是切片的值的復制,拷貝值與原值底層指向兩個不同的數(shù)組悦施,這種copy需要提前申請空間并扇。
func main() {
// 當元素數(shù)量超過容量
// 切片會在底層申請新的數(shù)組
slice := make([]int, 5, 5)
slice1 := slice
slice = append(slice, 1)
slice[0] = 1
fmt.Println(slice)//[1 0 0 0 0 1]
fmt.Println(slice1)//[0 0 0 0 0]
// copy 函數(shù)提供深拷貝功能
// 但需要在拷貝前申請空間
slice2 := make([]int, 4, 4)
slice3 := make([]int, 5, 5)
fmt.Println(copy(slice2, slice))//4
fmt.Println(copy(slice3, slice))//5
slice2[1] = 2
slice3[1] = 3
fmt.Println(slice)//[1 0 0 0 0 1]
fmt.Println(slice2)//[1 2 0 0]
fmt.Println(slice3)//[1 3 0 0 0]
}
- 容量擴容:切片的容量不足以支撐切片的append操作時,會自動擴容抡诞,擴容規(guī)則:
- 如果擴容需求大于當前容量的兩倍穷蛹,擴容后的容量為所需的最小容量
- 當前切片長度<1024,擴容當前容量為2倍,
- 當前切片長度>1024,每次擴容當前容量的1.25倍昼汗,循環(huán)擴容直至容量滿足需求
切片擴容之后肴熏,指向匿名數(shù)組的指針地址會發(fā)生變化。
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}
應用場景
切片的應用場景比較廣泛顷窒,任何需要動態(tài)擴展數(shù)組的地方都可以使用切片蛙吏。例如:接收前端傳入的固定類型的參數(shù)列表。
轉(zhuǎn)換
數(shù)組和切片
//copy 是值復制
var a = []int{1,2,3,4,5}
var b = [5]int{}
fmt.Println(copy(b[0:5],a))
fmt.Println(b)
a[0]=6
fmt.Println(a)
fmt.Println(b)
切片轉(zhuǎn)數(shù)組
s := make([]int,3)
var a = [3]int{1,2,3}
fmt.Println(copy(a[0:3],s)) //3
fmt.Println(s) //[1,2,3]
//copy 需要提前申請空間
s := make([]int,0)
var a = [3]int{1,2,3}
fmt.Println(copy(a[0:3],s)) //0
fmt.Println(s) //[]