天天看點

【go語言學習筆記】數組和切片

1.數組

go語言中也配有數組這種資料結構,它的定義方式類似

java

,每一種定義都是一種類型,比如:

var arr [50]int

var arr [100]int

,他們分别是

[50]int

類型和

[100]int

類型。

可以使用疊代器來周遊數組。

demo:

package main

import "fmt"

func main() {
	// 數組,同一個類型的集合
	var arr [50]int

	//操作數組,通過下标,從0開始到len-1

	// 一般for循環寫法
	for i := 0; i < len(arr); i++ {
		arr[i] = i * 2
		fmt.Println(arr[i])
	}

	//疊代器寫法
	for i := range arr {
		arr[i] = i
	}

	for i := range arr {
		fmt.Println(arr[i])
	}
}

           

2.二維數組

定義方式同上。

demo:

package main

import "fmt"

func main() {
	// 二維數組
	var a [3][4]int

	fmt.Println("a = ", a)
}
           

3.切片的建立

切片的底層是結構體,這裡的切片類似c++中的引用,隻是把底層數組(原數組)某段位址拷貝過去了,并沒有建立新的數組。

定義方式:

  1. 直接定義,類似python的清單切片
  2. 借助make函數,make(切片類型,長度,容量)
package main

import "fmt"

func main() {
	//自動推導類型,同時初始化
	s1 := []int{1, 2, 3, 4}
	fmt.Println("s1 = ", s1)

	//借助make函數, make(切片類型,長度, 容量)
	s2 := make([]int, 5, 10)
	fmt.Println("len = ", len(s2), "cap = ", cap(s2))
	//沒有指定容量,容量和長度一樣
	s3 := make([]int, 5)
	fmt.Println("len = ", len(s3), "cap = ", cap(s3))
}
           

4.切片的截取

這裡的截取類似python的切片,也是得到原數組的位址引用。

package main

import "fmt"

func main() {
	arr := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	//[low:high:max] 取下标從low開始至high-1的元素
	s1 := arr[:] //取整個數組
	fmt.Println("s1 = ", s1)

}

           

5.切片和數組的差別

數組[]裡面的長度是一個固定常量,數組不能修改長度,len和cap固定,而切片,[]裡面為空,或者…,切片的長度或容量可以不确定。

直接定義的切片像是動态擴容數組的替代品。

package main

import "fmt"

func main() {
	//切片和數組的差別
	//數組[]裡面的長度是一個固定常量,數組不能修改長度,len和cap固定
	a := [5]int{}
	fmt.Println("len = ", len(a), " cap = ", cap(a))

	//切片,[]裡面為空,或者...,切片的長度或容量可以不确定
	b := []int{}
	fmt.Println("len = ", len(b), "cap = ", cap(b))

	b = append(b, 11)
	fmt.Println("len = ", len(b), "cap = ", cap(b))

}

           

6.切片做函數參數

這樣傳入的切片像是引用傳遞,而不是數組的值傳遞,這樣可以提高效率,節約記憶體。

package main

import "fmt"
import "math/rand"
import "time"

func InitData(s []int) {
	//設定随機種子
	rand.Seed(time.Now().UnixNano())

	for i := 0; i < len(s); i++ {
		s[i] = rand.Intn(100)
	}
}

func BubbleSort(s []int) { //傳入一個數組的引用,,相當于傳指針
	n := len(s)

	for i := 0; i < n-1; i++ {
		for j := 0; j < n-i-1; j++ {
			if s[j] > s[j+1] {
				s[j], s[j+1] = s[j+1], s[j]
			}
		}
	}
}

func main() {
	n := 10

	// 建立一個切片,len = n
	s := make([]int, n)

	InitData(s) //初始化數組
	BubbleSort(s)
	fmt.Println("s = ", s)
}

           

7.數組的比較和指派

go語言支援數組的比較和指派,但隻支援

==

!=

,他會逐個比較每個元素是否值一樣,并且數組類型要相同才能比較和指派,比如

[50]int

類型和

[100]int

類型就不能比較和指派,因為他們不是同一個類型。

package main

import "fmt"

func main() {
	// 支援比較,隻支援 == 或 !=, 比較是不是每一個元素都一樣,2個數組比較,數組類型要一樣
	// 比如 [5]int 和 [6]int就不是一個類型

	a := [5]int{1, 2, 3, 4, 5}
	b := [5]int{1, 2, 3, 4, 5}
	c := [5]int{1, 2, 3}
	fmt.Println("a == b", a == b)
	fmt.Println("a == c", a == c)

	// 同類型的數組可以指派
	var d [5]int
	d = a
	fmt.Println("d = ", d)

	// 自動推導長度
	e := [...]int{1, 2, 3, 4}
	fmt.Println("e = ", e, "len(e) = ", len(e))
}

           

8.數組的初始化

這裡的初始化類似c語言中的初始化,并加入了指定位置初始化,若是隻初始化部分元素,未顯式初始化的其他元素都會被初始化為0。

package main

import "fmt"

func main() {
	//1. 全部初始化
	var a [5]int = [5]int{1, 2, 3, 4, 5}
	fmt.Println("a = ", a)

	b := [6]int{1, 2, 3, 4, 5, 6}
	fmt.Println("b = ", b)

	//2. 部分初始化,沒有初始化的元素自動指派為0
	c := [5]int{1, 2, 3}
	fmt.Println("c = ", c)

	//3. 指定元素初始化
	d := [5]int{2: 3, 4: 6}
	fmt.Println("d = ", d)
}

           

9.數組的切片

數組切片 [low:high:max],是原數組的引用,其中的參數意義如下

  • low: 下标的起點
  • high: 下标的終點,不包括該下标,左閉右開
  • max:為切片保留的原切片的最大下标(不含max)
  • cap : max - low 容量,因為切片是原數組的引用,是以用max減去起始的指針,就是引用數組的容量。
package main

import "fmt"

func main() {
	a := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 10}

	//數組切片 [low:high:max],是原數組的引用
	// low: 下标的起點
	// high: 下标的終點,不包括該下标,左閉右開
	// max:為切片保留的原切片的最大下标(不含max)
	// cap : max - low 容量,因為切片是原數組的引用,是以用max減去起始的指針,就是引用數組的容量
	slice := a[1:3:5]

	fmt.Println("slice = ", slice)
	fmt.Println("len(slice) = ", len(slice))
	fmt.Println("cap(slice) = ", cap(slice))
}