GO語言基礎知識(二)數組、切片、指針操作

一、指針的應用

二、數組的常見操作

三、切片的常見操作

四、make new內置函數的使用

GO語言中,基本數據類型是值傳遞,比如int float bool string以及數組和結構體;在進行賦值或者在進行函數參數傳遞的時候,其實傳遞的是其值的副本,並非傳遞的引用(切片、map、chan是引用傳遞),若要改變這些類型的值,需要使用指針。

<code>n1 := 100
n2 := &n1
//獲取指針,得到n1變量對應的帶有0x的16進制地址
fmt.Printf("%p \\n",n2)
//根據指針,獲得其對應的值
fmt.Printf("%d \\n",*n2)
//根據指針,改變其對應的值
*n2 = 200
//打印查看n1的值
fmt.Printf("%d \\n",n1)/<code>

數組的簡單操作

  • 顯式指定長度並聲明數組後根據下標賦值
<code>var array [10]int
array[0]=1
array[1]=2
fmt.Println(array)/<code>
  • 顯式指定長度並聲明的同時進行初始化
<code>var array1 = [10]int{1,2}
fmt.Println(array1)/<code>
  • 隱式指定length,根據後面給的值的個數自動判斷length
<code>var array2 = [...]int{1,2,3}
fmt.Println(array2)/<code>
  • 隱式指定length並根據下標初始化數組
<code>var array3 = [...]int{2:3,9:10}
fmt.Println(array3,len(array3),cap(array3))
//上面輸出 [0 0 3 0 0 0 0 0 0 10] 10 10/<code>
  • 數組的遍歷
<code>//方式1
for i:=0;i fmt.Print(array3[i])
}
fmt.Println()
//方式2
for i,v:= range array3{
fmt.Printf("%d-%v",i,v)
}
/<code>

切片的的基本操作,底層本質是數組,具有自動擴容的能力

<code>var sliceName []int
//聲明的切片在使用前必須經過初始化來分配內存否則引發panic異常

fmt.Println("sliceName is nil : ",sliceName==nil) //true
sliceName[0]=1 //拋異常panic/<code>
  • 初始化並初始賦值
<code>sliceName = []int{} 
//聲明長度和容量都是0的切片
fmt.Println("sliceName is nil : ",sliceName==nil) //false
fmt.Println(len(sliceName),cap(sliceName)) //0 0
sliceName = []int{1,2} //聲明切片並放入2個元素
fmt.Println(len(sliceName),cap(sliceName)) //2 2/<code>
  • 基於數組生成切片
<code>array5 := [...]int{1,2,3,4,5}
sliceName = array5[0:1] //前包含後不包含
fmt.Println(sliceName,len(sliceName),cap(sliceName)) //[1] 1 5
sliceName = array5[1:4] //特殊的可以簡寫如[1:] [:3] [:]
fmt.Println(sliceName,len(sliceName),cap(sliceName)) //[2,3,4] 3 4
sliceName[0]=999
fmt.Println(sliceName,array5)//改變切片的值會同步影響底層數組的值/<code>

總結:基於數組的切片,容量就是從開始切的位置開始到數組末尾的長度;因為切片的數據是存在底層數組中的,所以改變切邊的值必定會影響底層數組的值。

  • 切片再切片
<code>sliceName2 := sliceName[1:2]
fmt.Println(sliceName2,len(sliceName2),cap(sliceName2)) //[3] 1 3
總結:基於切片再切片//容量就是從開始切的位置開始到原底層數組末尾的長度(都是基於底層數組計算的)/<code>

總結:基於切片再切片,容量就是從開始切的位置開始到原底層數組末尾的長度(都是基於底層數組計算的)。

  • 基於make函數構造切片
<code>sliceName3 := make([]int,10,10) //長度和容量都是10的切片
sliceName3[2] =3 //切片賦值
fmt.Println(sliceName3,len(sliceName3),cap(sliceName3))//[0 0 3 0 0 0 0 0 0 0] 10 10
sliceName3 = append(sliceName3,11)
//添加元素有可能會觸發切片擴容(原底層數組不足以存儲的時候)
//擴容後切片的底層數組就是一個新的,不再是原有的了
fmt.Println(sliceName3,len(sliceName3),cap(sliceName3))//[0 0 3 0 0 0 0 0 0 0 11] 11 20/<code>
  • 遍歷切片
<code>for i:=0;i< len(sliceName3);i++{
fmt.Print(sliceName3[i])
}
for _,value := range sliceName3 {
fmt.Print(value)
}/<code>
  • 複製切片,超過目標切片length以外的數據將不被複制
<code>sliceName4 := make([]int,3,12)
copy(sliceName4,sliceName3)
fmt.Println(sliceName4) //[0 0 3]/<code>
  • 刪除切片元素
<code>array6 := [10]int{0:1,1:2,9:10}
sliceName5 := array6[:]
fmt.Println("原數組",array6) //[1 2 0 0 0 0 0 0 0 10]
sliceName5 = append(sliceName5[:1],sliceName5[2:]...)
//數組的刪除操作會導致底層數組一部分元素複製換位
fmt.Println("原數組",array6) //[1 0 0 0 0 0 0 0 10 10]
fmt.Println(sliceName5,len(sliceName5),cap(sliceName5)) //[1 0 0 0 0 0 0 0 10] len 9 cap 10
sliceName5 = append(sliceName5,11)
fmt.Println("原數組",array6) // [1 0 0 0 0 0 0 0 10 11]
fmt.Println(sliceName5,len(sliceName5),cap(sliceName5)) //[1 0 0 0 0 0 0 0 10 11] 10 10
sliceName5 = append(sliceName5,12)
fmt.Println("原數組",array6)
//原數組 [1 0 0 0 0 0 0 0 10 11] 不再變化,因為原數組長度已不夠,新創建了一個數組並擴容
fmt.Println(sliceName5,len(sliceName5),cap(sliceName5)) //[1 0 0 0 0 0 0 0 10 11 12] 11 20/<code>

make new內置函數

make用來初始化slice、map、chan引用類型數據結構並申請內存空間

new用來為基本數據類型比如int、string等申請內存

<code>fmt.Printf("%T\\n",new(int))  //得到int類型的指針*int
fmt.Printf("%T\\n",make(map[string]int,10))//得到一個map的引用/<code>


讓我們一起進步學習,共同成長;歡迎大家關注微信公眾號:芝麻技術棧


分享到:


相關文章: