1. 数组
- 数组是同一类型数据的固定长度的序列
- 数组的定义格式为 var 数组名[长度]类型
- 数组长度是其类型的一部分,一旦定义,不能更改,例如var a[5]int和var a[8]int这两个数组不是同一类型
- 数组使用下表访问,第一个元素从0开始,最后一个为长度-1,若访问越界会Panic
- 数组是值类型,若赋值或当成参数传递会复制整个数组,若改变副本值原始数组不会发生改变
- 支持 “==“或”!=” 操作符,因为内存总是被初始化过的
- 数组指针为*[length]T
- 指针数组为[length]*T
- 可以使用for range 遍历数组
- 可以使用len()方法获取数组长度
- arr[start:end] 从start下标获取到end下标
- arr[start:] 从start下标获取到结尾
- arr[:end] 从开始获取到end下标
2. 切片
- 因为数组长度是固定的,在实际的应用场景中不够灵活,不能实现动态的扩容,所以切片诞生了
- 切片是数组的一个引用,并不是数组或数组指针,因此切片是引用类型
- 切片的定义有2种方式:1. var 变量名 []类型 2. var 变量名 = make([]T,length,capacity),其中capacity是可选参数
- 需要注意的是切片的读写操作实际目标是底层数组
- len 可以用来获取切片长度
- cap 可以用来获取切片容量,适用于切片和map
- append 向切片尾部添加元素,需要注意的是,append后返回的是新的切片,当超过切片cap进行append时,length递增1,cap成倍增长
- copy 方法可以用作切片的复制,但需要注意以下几点:1. 不同类型的切片无法复制 2. 若slice1的长度大于slice2的长度,slice2对应位置的元素覆盖slice1对应位置的元素 3. 若slice1的长度小于slice2的长度,多余元素不处理
- 同样使用for range对切片进行遍历
- 字符串在底层是一个byte数组,所以也可以进行切片操作
var s1 []int
fmt.Println(s1)
var s2 = make([]int, 0)
fmt.Println(s2)
var s3 = make([]int, 0, 0)
fmt.Println(s3)
var arr = [...]int{1,2,3,4,5,6,7,8,9}
var s4 = arr[:]
fmt.Println(s4)
s4 = arr[2:4]
fmt.Println(s4)
s4 = arr[2:]
fmt.Println(s4)
s4 = arr[:4]
fmt.Println(s4)
s := make([]int,0,0)
s = append(s,119)
fmt.Printf("%p\n",&s)
fmt.Println(len(s))
fmt.Println(cap(s))
s = append(s,120)
fmt.Printf("%p\n",&s)
fmt.Println(len(s))
fmt.Println(cap(s))
s = append(s,114)
fmt.Printf("%p\n",&s)
fmt.Println(len(s))
fmt.Println(cap(s))
cs1 := []int{1, 2, 3}
cs2 := []int{4, 5}
cs3 := []int{6, 7, 8, 9}
copy(cs1, cs2)
fmt.Println(cs1)
fmt.Println(cs2)
copy(cs2, cs3)
fmt.Println(cs2)
fmt.Println(cs3)
data := [][]string{
[]string{"a","b"},
[]string{"c","d"},
[]string{"e","f"},
}
fmt.Println(data)
type user struct {
name string
age int
}
users := [5]user{}
users[0].name = "Mossil"
users[0].age = 18
fmt.Println(users)
str := "hello word"
str1 := str[0:5]
fmt.Println(str1)
str2 := str[6:]
fmt.Println(str2)
zstr := "你好 世界"
zs := []rune(zstr)
zstr1 := string(zs[:])
fmt.Println(zstr1)