Go 切片数组

数组

数组只能存储同一种数据类型的数据
数组长度一经初始化,不能够修改

数组的声明

var 数组名称 [长度]数据类型

获取数组的长度使用内置函数len(arr)
获取数组的容量使用内置函数cap(arr)

func main() {

// var 数组名词 [长度]数据类型
var arr [5]int
arr[0] = 1
arr[1] = 2

// 没有赋值的内容, 默认为数组数据类型的零值
fmt.Println(arr[2])	// 0

fmt.Println("数组的长度为:", len(arr))	// 5
fmt.Println("数组的容量为:", cap(arr))	// 3

}

数组的创建

数组创建有四种方式

func main() {

// 0. 创建时制定长度, 不赋值
var arr0 [5]int
arr0[0] = 1
fmt.Println(arr0[0])	// 1

// 1. 创建时, 直接将值赋值到数组里面
arr := [3]int{1,2,3}
fmt.Println(arr[2])		// 3

// 2. 指定对应位置的值
arr1 := [3]int{0:3, 1:2, 2:1}
fmt.Println(arr1[0])	// 3

// 3. 创建时, 不指定数组长度, 由初始化赋值长度自动推断
arr2 := [...]int{1, 2, 3, 4, 5}
fmt.Println("arr2 len: ", len(arr2))	// 5
fmt.Println("arr2 cap: ", cap(arr2))	// 5

}

数组的遍历

func main() {

arr := [...]int{1,2,3,4,5}

// range方式遍历
for a := range arr {
	fmt.Println(a)
}

fmt.Println("---")

// for循环方式
for idx, a := range arr {
	fmt.Println("idx=", idx, "arr=", a)
}

}

二维数组

func main() {

// 定义, 后赋值
// arr1 := [2][3]int

// 定义时初始化
arr := [2][3]int{{1,2,3},{11,22,33}}

printArr(arr)

//[0][0]=1
//[0][1]=2
//[0][2]=3
//[1][0]=11
//[1][1]=22
//[1][2]=33

fmt.Println("---")

// 通过下标修改数组元素
arr[1][0] = 111

printArr(arr)

//[0][0]=1
//[0][1]=2
//[0][2]=3
//[1][0]=111
//[1][1]=22
//[1][2]=33

}

func printArr(arr [2][3]int) {
for one, ints := range arr {
for two, i2 := range ints {
fmt.Println(fmt.Sprintf("[%v][%v]=%v", one, two, i2))
}
}
}

切片Slice

切片的声明

它与数组的唯一区别,就是[]中不指定长度

var 切片名称 []数据类型
切片名称 := make([]数据类型, 初始数据, 初始容量)

// 声明一个切片slice
var slice []int
// 初始化一个长度为2, 容量为5的切片
slice := make([]int, 2, 5)

切片的创建与扩容

通过make函数创建切片
通过append添加元素
切片的扩容是成倍的,扩容后内存地址改变

func main() {

// 初始化一个长度为2, 容量为5的切片
slice := make([]int, 2, 5)

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

// 切片通过append添加元素
slice = append(slice, 2, 3, 4, 5, 6)
fmt.Println(slice)
// 当切片容量不够时, 成倍扩容
fmt.Println("len=", len(slice), "cap=", cap(slice))
//[0 0]
//len= 2 cap= 5
//[0 0 2 3 4 5 6]
//len= 7 cap= 10


// 添加一组切片到另一切片中
slice1 := append(slice)
// 修改源切片会影响到新切片, 因为是浅拷贝
slice[1] = 1
fmt.Println(slice)
fmt.Println(slice1)
//[0 1 2 3 4 5 6]
//[0 1 2 3 4 5 6]

s1 := make([]int, 0, 3)
fmt.Printf("地址%p,长度%d,容量%d\n", s1, len(s1), cap(s1))
s1 = append(s1, 1, 2)
fmt.Printf("地址%p,长度%d,容量%d\n", s1, len(s1), cap(s1))
s1 = append(s1, 3, 4, 5)
fmt.Printf("地址%p,长度%d,容量%d\n", s1, len(s1), cap(s1))

//地址0xc000016160,长度0,容量3
//地址0xc000016160,长度2,容量3
//地址0xc00001c180,长度5,容量6

}

make()与new() 的区别

make()是Go语言中的内置函数,主要用于创建并初始化slice切片类型,或者map字典类型,或者channel通道类型数据。他与new方法的区别是。new用于各种数据类型的内存分配,在Go语言中认为他返回的是一个指针。指向的是一个某种类型的零值。make 返回的是一个有着初始值的非零值。

func main() {

slice1 := new([]int)
fmt.Println(slice1) // &[]

slice2 := make([]int, 3)
fmt.Println(slice2)	// [0 0 0]

//结果出错 slice1是一个空指针 invalid operation: slice1[0] (type *[]int does not support indexing)
fmt.Println(slice1[0])
//结果为 0 因为已经初始化了
fmt.Println(slice2[0])

}