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++中的引用,只是把底层数组(原数组)某段地址拷贝过去了,并没有创建新的数组。
定义方式:
- 直接定义,类似python的列表切片
- 借助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))
}