一、数组:
1、① 数组作为参数传递时,传递的是值得拷贝。
② 数组的容量和长度是一样的。cap() 函数和 len() 函数均输出数组的容量
2、数组有三种创建方式:
var arr1 [5]int //0 0 0 0 0
arr2 := [3]int{1, 3, 5} //1 3 5
arr3 := [...]int{2, 4, 6, 8, 10}//2 4 6 8 10
3、数组的遍历(切片也这样遍历):
//for i := range arr //i是索引
for i,v := range arr { //i是索引,v是值
fmt.Println(i,v)
}
二、切片
一个slice是一个数组某个部分的引用。在内存中,它是一个包含3个域的结构体:指向slice中第一个元素的指针,slice的长度,以及slice的容量
1、①切片作为参数传递时,传递的是地址的拷贝,
②切片长度可变 len()、容量固定cap() 的相同的元素序列。切片本质是一个数组。容量固定是因为数组的长度是固定的,切片的容量即隐藏数组的长度。长度可变指的是在数组长度的范围内可变。
③append 用来向数组末尾追加数据,当在使用 append 的时候,如果 cap==len 了这个时候就会新开辟一块更大内存,然后把之前的数据复制过去。在append的时候放大cap是有规律的。在 cap 小于1024的情况下是每次扩大到 2 * cap ,当大于1024之后就每次扩大到 1.25 * cap
2、创建切片有四种方式:
var s1 []int //0 0 (len,cap)Zero value for slice is nil
s2 := []int{2, 4, 6, 8} //4 4
s3 := make([]int, 22) //22 22
s4 := make([]int, 21, 22) //21 22
3、对切片的操作
package main
import "fmt"
func updateSlice(s []int) {
s[0] = 100
}
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
//下面的切片s1,s2,s3,s4是同一个一个隐藏数组arr的引用
fmt.Println("arr[2:6] =", arr[2:6]) //2 3 4 5 (4,6) (括号里面的是len和cap)
fmt.Println("arr[:6] =", arr[:6]) //0 1 2 3 4 5 (6,8)
s1 := arr[2:] //2 3 4 5 6 7 (6,6)
s2 := arr[:] //0 1 2 3 4 5 6 7 (8,8)
updateSlice(s1) //改变切片中的某个元素,因为传递的是引用,所以改变的是底层隐藏数组,所以与它相关的都改变
fmt.Println(s1) //100 3 4 5 6 7 (6,6)
fmt.Println(arr) //0 1 100 3 4 5 6 7 (8,8)
updateSlice(s2)
fmt.Println(s2) //100 1 100 3 4 5 6 7 (8,8)
fmt.Println(arr) //100 1 100 3 4 5 6 7 (8,8)
s2 = s2[:5] //100 1 100 3 4 (5,8)
s2 = s2[2:] //100 3 4 (3,6)
arr[0], arr[2] = 0, 2
fmt.Println("arr =", arr) //0 1 2 3 4 5 6 7 (8,8)
s1 = arr[2:6] //2 3 4 5 (4,6)
s2 = s1[3:5] //5 6 (2,3) [s1[3], s1[4]] (注意,这里输出了6),切片可以向后扩展,不可以向前扩展,arr,s1,s2见下图
s3 := append(s2, 10) //[5 6 10]
s4 := append(s3, 11) //[5 6 10 11]
fmt.Println("s3, s4, s5 =", s3, s4)
}